New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

playwright-core

Package Overview
Dependencies
Maintainers
4
Versions
4772
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

playwright-core - npm Package Compare versions

Comparing version 1.50.0-beta-1731498714000 to 1.50.0-beta-1737137869000

lib/server/recorder/chat.js

33

browsers.json

@@ -6,35 +6,31 @@ {

"name": "chromium",
"revision": "1148",
"revision": "1155",
"installByDefault": true,
"browserVersion": "131.0.6778.33"
"browserVersion": "133.0.6943.16"
},
{
"name": "chromium-headless-shell",
"revision": "1148",
"installByDefault": true,
"browserVersion": "131.0.6778.33"
},
{
"name": "chromium-tip-of-tree",
"revision": "1277",
"revision": "1293",
"installByDefault": false,
"browserVersion": "132.0.6834.0"
"browserVersion": "133.0.6943.0"
},
{
"name": "firefox",
"revision": "1466",
"revision": "1471",
"installByDefault": true,
"browserVersion": "132.0"
"browserVersion": "134.0"
},
{
"name": "firefox-beta",
"revision": "1465",
"revision": "1467",
"installByDefault": false,
"browserVersion": "132.0b8"
"browserVersion": "133.0b9"
},
{
"name": "webkit",
"revision": "2104",
"revision": "2123",
"installByDefault": true,
"revisionOverrides": {
"debian11-x64": "2105",
"debian11-arm64": "2105",
"mac10.14": "1446",

@@ -53,3 +49,3 @@ "mac10.15": "1616",

"name": "ffmpeg",
"revision": "1010",
"revision": "1011",
"installByDefault": true,

@@ -62,2 +58,7 @@ "revisionOverrides": {

{
"name": "winldd",
"revision": "1007",
"installByDefault": false
},
{
"name": "android",

@@ -64,0 +65,0 @@ "revision": "1001",

@@ -42,3 +42,3 @@ "use strict";

devices = devices.filter(d => d.serial === options.deviceSerialNumber);
if (devices.length === 0) throw new Error(`No device with serial number '${options.deviceSerialNumber}' not found`);
if (devices.length === 0) throw new Error(`No device with serial number '${options.deviceSerialNumber}' was found`);
}

@@ -45,0 +45,0 @@ if (devices.length > 1) throw new Error(`More than one device found. Please specify deviceSerialNumber`);

@@ -19,3 +19,2 @@ "use strict";

var playwright = _interopRequireWildcard(require("../.."));
var _child_process = require("child_process");
var _utils = require("../utils");

@@ -60,3 +59,3 @@ var _server = require("../server");

$ open -b webkit https://example.com`);
commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions', [['-o, --output <file name>', 'saves the generated script to a file'], ['--target <language>', `language to generate, one of javascript, playwright-test, python, python-async, python-pytest, csharp, csharp-mstest, csharp-nunit, java, java-junit`, codegenId()], ['--save-trace <filename>', 'record a trace for the session and save it to a file'], ['--test-id-attribute <attributeName>', 'use the specified attribute to generate data test ID selectors']]).action(function (url, options) {
commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions', [['-o, --output <file name>', 'saves the generated script to a file'], ['--target <language>', `language to generate, one of javascript, playwright-test, python, python-async, python-pytest, csharp, csharp-mstest, csharp-nunit, java, java-junit`, codegenId()], ['--test-id-attribute <attributeName>', 'use the specified attribute to generate data test ID selectors']]).action(function (url, options) {
codegen(options, url).catch(logErrorAndExit);

@@ -69,31 +68,35 @@ }).addHelpText('afterAll', `

$ codegen -b webkit https://example.com`);
_utilsBundle.program.command('debug <app> [args...]', {
hidden: true
}).description('run command in debug mode: disable timeout, open inspector').allowUnknownOption(true).action(function (app, options) {
(0, _child_process.spawn)(app, options, {
env: {
...process.env,
PWDEBUG: '1'
},
stdio: 'inherit'
});
}).addHelpText('afterAll', `
Examples:
$ debug node test.js
$ debug npm run test`);
function suggestedBrowsersToInstall() {
return _server.registry.executables().filter(e => e.installType !== 'none' && e.type !== 'tool').map(e => e.name).join(', ');
}
function checkBrowsersToInstall(args) {
function defaultBrowsersToInstall(options) {
let executables = _server.registry.defaultExecutables();
if (options.noShell) executables = executables.filter(e => e.name !== 'chromium-headless-shell');
if (options.onlyShell) executables = executables.filter(e => e.name !== 'chromium');
return executables;
}
function checkBrowsersToInstall(args, options) {
if (options.noShell && options.onlyShell) throw new Error(`Only one of --no-shell and --only-shell can be specified`);
const faultyArguments = [];
const executables = [];
for (const arg of args) {
const handleArgument = arg => {
const executable = _server.registry.findExecutable(arg);
if (!executable || executable.installType === 'none') faultyArguments.push(arg);else executables.push(executable);
if ((executable === null || executable === void 0 ? void 0 : executable.browserName) === 'chromium') executables.push(_server.registry.findExecutable('ffmpeg'));
};
for (const arg of args) {
if (arg === 'chromium') {
if (!options.onlyShell) handleArgument('chromium');
if (!options.noShell) handleArgument('chromium-headless-shell');
} else {
handleArgument(arg);
}
}
if (process.platform === 'win32') executables.push(_server.registry.findExecutable('winldd'));
if (faultyArguments.length) throw new Error(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${suggestedBrowsersToInstall()}`);
return executables;
}
_utilsBundle.program.command('install [browser...]').description('ensure browsers necessary for this version of Playwright are installed').option('--with-deps', 'install system dependencies for browsers').option('--dry-run', 'do not execute installation, only print information').option('--force', 'force reinstall of stable browser channels').action(async function (args, options) {
_utilsBundle.program.command('install [browser...]').description('ensure browsers necessary for this version of Playwright are installed').option('--with-deps', 'install system dependencies for browsers').option('--dry-run', 'do not execute installation, only print information').option('--force', 'force reinstall of stable browser channels').option('--only-shell', 'only install headless shell when installing chromium').option('--no-shell', 'do not install chromium headless shell').action(async function (args, options) {
// For '--no-shell' option, commander sets `shell: false` instead.
if (options.shell === false) options.noShell = true;
if ((0, _utils.isLikelyNpxGlobal)()) {

@@ -104,3 +107,3 @@ console.error((0, _utils.wrapInASCIIBox)([`WARNING: It looks like you are running 'npx playwright install' without first`, `installing your project's dependencies.`, ``, `To avoid unexpected behavior, please install your dependencies first, and`, `then run Playwright's install command:`, ``, ` npm install`, ` npx playwright install`, ``, `If your project does not yet depend on Playwright, first install the`, `applicable npm package (most commonly @playwright/test), and`, `then run Playwright's install command to download the browsers:`, ``, ` npm install @playwright/test`, ` npx playwright install`, ``].join('\n'), 1));

const hasNoArguments = !args.length;
const executables = hasNoArguments ? _server.registry.defaultExecutables() : checkBrowsersToInstall(args);
const executables = hasNoArguments ? defaultBrowsersToInstall(options) : checkBrowsersToInstall(args, options);
if (options.withDeps) await _server.registry.installDeps(executables, !!options.dryRun);

@@ -153,3 +156,3 @@ if (options.dryRun) {

try {
if (!args.length) await _server.registry.installDeps(_server.registry.defaultExecutables(), !!options.dryRun);else await _server.registry.installDeps(checkBrowsersToInstall(args), !!options.dryRun);
if (!args.length) await _server.registry.installDeps(defaultBrowsersToInstall({}), !!options.dryRun);else await _server.registry.installDeps(checkBrowsersToInstall(args, {}), !!options.dryRun);
} catch (e) {

@@ -211,5 +214,3 @@ console.log(`Failed to install browser dependencies\n${e}`);

});
_utilsBundle.program.command('run-server', {
hidden: true
}).option('--port <port>', 'Server port').option('--host <host>', 'Server host').option('--path <path>', 'Endpoint Path', '/').option('--max-clients <maxClients>', 'Maximum clients').option('--mode <mode>', 'Server mode, either "default" or "extension"').action(function (options) {
_utilsBundle.program.command('run-server').option('--port <port>', 'Server port').option('--host <host>', 'Server host').option('--path <path>', 'Endpoint Path', '/').option('--max-clients <maxClients>', 'Maximum clients').option('--mode <mode>', 'Server mode, either "default" or "extension"').action(function (options) {
(0, _driver.runServer)({

@@ -308,3 +309,4 @@ port: options.port ? +options.port : undefined,

try {
const [width, height] = options.viewportSize.split(',').map(n => parseInt(n, 10));
const [width, height] = options.viewportSize.split(',').map(n => +n);
if (isNaN(width) || isNaN(height)) throw new Error('bad values');
contextOptions.viewport = {

@@ -315,3 +317,3 @@ width,

} catch (e) {
throw new Error('Invalid viewport size format: use "width, height", for example --viewport-size=800,600');
throw new Error('Invalid viewport size format: use "width,height", for example --viewport-size="800,600"');
}

@@ -376,5 +378,2 @@ }

closingBrowser = true;
if (options.saveTrace) await context.tracing.stop({
path: options.saveTrace
});
if (options.saveStorage) await context.storageState({

@@ -402,6 +401,2 @@ path: options.saveStorage

context.setDefaultNavigationTimeout(timeout);
if (options.saveTrace) await context.tracing.start({
screenshots: true,
snapshots: true
});

@@ -481,3 +476,2 @@ // Omit options that we add automatically for presentation purpose.

mode: 'recording',
codegenMode: process.env.PW_RECORDER_IS_TRACE_VIEWER ? 'trace-events' : 'actions',
testIdAttributeName,

@@ -484,0 +478,0 @@ outputFile: outputFile ? _path.default.resolve(outputFile) : undefined,

@@ -129,26 +129,17 @@ "use strict";

return await this._wrapApiCall(async apiZone => {
const {
apiName,
frames,
csi,
callCookie,
stepId
} = apiZone.reported ? {
apiName: undefined,
csi: undefined,
callCookie: undefined,
frames: [],
stepId: undefined
} : apiZone;
apiZone.reported = true;
let currentStepId = stepId;
if (csi && apiName) {
const out = {};
csi.onApiCallBegin(apiName, params, frames, callCookie, out);
currentStepId = out.stepId;
}
return await this._connection.sendMessageToServer(this, prop, validator(params, '', {
const validatedParams = validator(params, '', {
tChannelImpl: tChannelImplToWire,
binary: this._connection.rawBuffers() ? 'buffer' : 'toBase64'
}), apiName, frames, currentStepId);
});
if (!apiZone.isInternal && !apiZone.reported) {
// Reporting/tracing/logging this api call for the first time.
apiZone.params = params;
apiZone.reported = true;
this._instrumentation.onApiCallBegin(apiZone);
logApiCall(this._logger, `=> ${apiZone.apiName} started`);
return await this._connection.sendMessageToServer(this, prop, validatedParams, apiZone.apiName, apiZone.frames, apiZone.stepId);
}
// Since this api call is either internal, or has already been reported/traced once,
// passing undefined apiName will avoid an extra unneeded tracing entry.
return await this._connection.sendMessageToServer(this, prop, validatedParams, undefined, [], undefined);
});

@@ -166,41 +157,31 @@ };

const logger = this._logger;
const apiZone = _zones.zones.zoneData('apiZone');
if (apiZone) return await func(apiZone);
const existingApiZone = _zones.zones.zoneData('apiZone');
if (existingApiZone) return await func(existingApiZone);
if (isInternal === undefined) isInternal = this._isInternalType;
const stackTrace = (0, _stackTrace.captureLibraryStackTrace)();
let apiName = stackTrace.apiName;
const frames = stackTrace.frames;
if (isInternal === undefined) isInternal = this._isInternalType;
if (isInternal) apiName = undefined;
// Enclosing zone could have provided the apiName and wallTime.
const expectZone = _zones.zones.zoneData('expectZone');
const stepId = expectZone === null || expectZone === void 0 ? void 0 : expectZone.stepId;
if (!isInternal && expectZone) apiName = expectZone.title;
// If we are coming from the expectZone, there is no need to generate a new
// step for the API call, since it will be generated by the expect itself.
const csi = isInternal || expectZone ? undefined : this._instrumentation;
const callCookie = {};
const apiZone = {
apiName: stackTrace.apiName,
frames: stackTrace.frames,
isInternal,
reported: false,
userData: undefined,
stepId: undefined
};
try {
logApiCall(logger, `=> ${apiName} started`, isInternal);
const apiZone = {
apiName,
frames,
isInternal,
reported: false,
csi,
callCookie,
stepId
};
const result = await _zones.zones.run('apiZone', apiZone, async () => await func(apiZone));
csi === null || csi === void 0 || csi.onApiCallEnd(callCookie);
logApiCall(logger, `<= ${apiName} succeeded`, isInternal);
if (!isInternal) {
logApiCall(logger, `<= ${apiZone.apiName} succeeded`);
this._instrumentation.onApiCallEnd(apiZone);
}
return result;
} catch (e) {
const innerError = (process.env.PWDEBUGIMPL || (0, _utils.isUnderTest)()) && e.stack ? '\n<inner error>\n' + e.stack : '';
if (apiName && !apiName.includes('<anonymous>')) e.message = apiName + ': ' + e.message;
if (apiZone.apiName && !apiZone.apiName.includes('<anonymous>')) e.message = apiZone.apiName + ': ' + e.message;
const stackFrames = '\n' + (0, _stackTrace.stringifyStackFrames)(stackTrace.frames).join('\n') + innerError;
if (stackFrames.trim()) e.stack = e.message + stackFrames;else e.stack = '';
csi === null || csi === void 0 || csi.onApiCallEnd(callCookie, e);
logApiCall(logger, `<= ${apiName} failed`, isInternal);
if (!isInternal) {
apiZone.error = e;
logApiCall(logger, `<= ${apiZone.apiName} failed`);
this._instrumentation.onApiCallEnd(apiZone);
}
throw e;

@@ -225,4 +206,3 @@ }

exports.ChannelOwner = ChannelOwner;
function logApiCall(logger, message, isNested) {
if (isNested) return;
function logApiCall(logger, message) {
if (logger && logger.isEnabled('api', 'info')) logger.log('api', 'info', message, [], {

@@ -229,0 +209,0 @@ color: 'cyan'

@@ -23,2 +23,4 @@ "use strict";

// Instrumentation can mutate the data, for example change apiName or stepId.
function createInstrumentation() {

@@ -25,0 +27,0 @@ const listeners = [];

@@ -79,5 +79,5 @@ "use strict";

this._instrumentation = void 0;
this._instrumentation = instrumentation || (0, _clientInstrumentation.createInstrumentation)();
this._localUtils = localUtils;
this._rootObject = new Root(this);
this._localUtils = localUtils;
this._instrumentation = instrumentation || (0, _clientInstrumentation.createInstrumentation)();
}

@@ -144,3 +144,3 @@ markAsRemote() {

// when we receive events from the server, we would be in an API zone.
_utils.zones.exitZones(() => this.onmessage({
_utils.zones.empty().run(() => this.onmessage({
...message,

@@ -147,0 +147,0 @@ metadata

@@ -53,2 +53,3 @@ "use strict";

this._fallbackOverrides = {};
this.markAsInternalType();
this._redirectedFrom = Request.fromNullable(initializer.redirectedFrom);

@@ -514,2 +515,3 @@ if (this._redirectedFrom) this._redirectedFrom._redirectedTo = this;

this._finishedPromise = new _manualPromise.ManualPromise();
this.markAsInternalType();
this._provisionalHeaders = new RawHeaders(initializer.headers);

@@ -664,3 +666,3 @@ this._request = Request.from(this._initializer.request);

this.handler = handler;
this._svedZone = _utils.zones.currentZone();
this._svedZone = _utils.zones.current().without('apiZone');
}

@@ -667,0 +669,0 @@ static prepareInterceptionPatterns(handlers) {

@@ -38,3 +38,3 @@ "use strict";

this._channelOwner = channelOwner;
this._savedZone = _utils.zones.currentZone();
this._savedZone = _utils.zones.current().without('apiZone');
this._channelOwner._channel.waitForEventInfo({

@@ -41,0 +41,0 @@ info: {

@@ -7,2 +7,2 @@ "use strict";

exports.source = void 0;
const source = exports.source = "\nvar __commonJS = obj => {\n let required = false;\n let result;\n return function __require() {\n if (!required) {\n required = true;\n let fn;\n for (const name in obj) { fn = obj[name]; break; }\n const module = { exports: {} };\n fn(module.exports, module);\n result = module.exports;\n }\n return result;\n }\n};\nvar __export = (target, all) => {for (var name in all) target[name] = all[name];};\nvar __toESM = mod => ({ ...mod, 'default': mod });\nvar __toCommonJS = mod => ({ ...mod, __esModule: true });\n\n\n// packages/playwright-core/src/server/injected/recorder/pollingRecorder.ts\nvar pollingRecorder_exports = {};\n__export(pollingRecorder_exports, {\n PollingRecorder: () => PollingRecorder,\n default: () => pollingRecorder_default\n});\nmodule.exports = __toCommonJS(pollingRecorder_exports);\n\n// packages/playwright-core/src/server/injected/recorder/clipPaths.ts\nvar svgJson = { \"tagName\": \"svg\", \"children\": [{ \"tagName\": \"defs\", \"children\": [{ \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-gripper\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"d\": \"M5 3h2v2H5zm0 4h2v2H5zm0 4h2v2H5zm4-8h2v2H9zm0 4h2v2H9zm0 4h2v2H9z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-circle-large-filled\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"d\": \"M8 1a6.8 6.8 0 0 1 1.86.253 6.899 6.899 0 0 1 3.083 1.805 6.903 6.903 0 0 1 1.804 3.083C14.916 6.738 15 7.357 15 8s-.084 1.262-.253 1.86a6.9 6.9 0 0 1-.704 1.674 7.157 7.157 0 0 1-2.516 2.509 6.966 6.966 0 0 1-1.668.71A6.984 6.984 0 0 1 8 15a6.984 6.984 0 0 1-1.86-.246 7.098 7.098 0 0 1-1.674-.711 7.3 7.3 0 0 1-1.415-1.094 7.295 7.295 0 0 1-1.094-1.415 7.098 7.098 0 0 1-.71-1.675A6.985 6.985 0 0 1 1 8c0-.643.082-1.262.246-1.86a6.968 6.968 0 0 1 .711-1.667 7.156 7.156 0 0 1 2.509-2.516 6.895 6.895 0 0 1 1.675-.704A6.808 6.808 0 0 1 8 1z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-inspect\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M1 3l1-1h12l1 1v6h-1V3H2v8h5v1H2l-1-1V3zm14.707 9.707L9 6v9.414l2.707-2.707h4zM10 13V8.414l3.293 3.293h-2L10 13z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-whole-word\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M0 11H1V13H15V11H16V14H15H1H0V11Z\" } }, { \"tagName\": \"path\", \"attrs\": { \"d\": \"M6.84048 11H5.95963V10.1406H5.93814C5.555 10.7995 4.99104 11.1289 4.24625 11.1289C3.69839 11.1289 3.26871 10.9839 2.95718 10.6938C2.64924 10.4038 2.49527 10.0189 2.49527 9.53906C2.49527 8.51139 3.10041 7.91341 4.3107 7.74512L5.95963 7.51416C5.95963 6.57959 5.58186 6.1123 4.82632 6.1123C4.16389 6.1123 3.56591 6.33789 3.03238 6.78906V5.88672C3.57307 5.54297 4.19612 5.37109 4.90152 5.37109C6.19416 5.37109 6.84048 6.05501 6.84048 7.42285V11ZM5.95963 8.21777L4.63297 8.40039C4.22476 8.45768 3.91682 8.55973 3.70914 8.70654C3.50145 8.84977 3.39761 9.10579 3.39761 9.47461C3.39761 9.74316 3.4925 9.96338 3.68228 10.1353C3.87564 10.3035 4.13166 10.3877 4.45035 10.3877C4.8872 10.3877 5.24706 10.2355 5.52994 9.93115C5.8164 9.62321 5.95963 9.2347 5.95963 8.76562V8.21777Z\" } }, { \"tagName\": \"path\", \"attrs\": { \"d\": \"M9.3475 10.2051H9.32601V11H8.44515V2.85742H9.32601V6.4668H9.3475C9.78076 5.73633 10.4146 5.37109 11.2489 5.37109C11.9543 5.37109 12.5057 5.61816 12.9032 6.1123C13.3042 6.60286 13.5047 7.26172 13.5047 8.08887C13.5047 9.00911 13.2809 9.74674 12.8333 10.3018C12.3857 10.8532 11.7734 11.1289 10.9964 11.1289C10.2695 11.1289 9.71989 10.821 9.3475 10.2051ZM9.32601 7.98682V8.75488C9.32601 9.20964 9.47282 9.59635 9.76644 9.91504C10.0636 10.2301 10.4396 10.3877 10.8944 10.3877C11.4279 10.3877 11.8451 10.1836 12.1458 9.77539C12.4502 9.36719 12.6024 8.79964 12.6024 8.07275C12.6024 7.46045 12.4609 6.98063 12.1781 6.6333C11.8952 6.28597 11.512 6.1123 11.0286 6.1123C10.5166 6.1123 10.1048 6.29134 9.7933 6.64941C9.48177 7.00391 9.32601 7.44971 9.32601 7.98682Z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-eye\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"d\": \"M7.99993 6.00316C9.47266 6.00316 10.6666 7.19708 10.6666 8.66981C10.6666 10.1426 9.47266 11.3365 7.99993 11.3365C6.52715 11.3365 5.33324 10.1426 5.33324 8.66981C5.33324 7.19708 6.52715 6.00316 7.99993 6.00316ZM7.99993 7.00315C7.07946 7.00315 6.33324 7.74935 6.33324 8.66981C6.33324 9.59028 7.07946 10.3365 7.99993 10.3365C8.9204 10.3365 9.6666 9.59028 9.6666 8.66981C9.6666 7.74935 8.9204 7.00315 7.99993 7.00315ZM7.99993 3.66675C11.0756 3.66675 13.7307 5.76675 14.4673 8.70968C14.5344 8.97755 14.3716 9.24908 14.1037 9.31615C13.8358 9.38315 13.5643 9.22041 13.4973 8.95248C12.8713 6.45205 10.6141 4.66675 7.99993 4.66675C5.38454 4.66675 3.12664 6.45359 2.50182 8.95555C2.43491 9.22341 2.16348 9.38635 1.89557 9.31948C1.62766 9.25255 1.46471 8.98115 1.53162 8.71321C2.26701 5.76856 4.9229 3.66675 7.99993 3.66675Z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-symbol-constant\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M4 6h8v1H4V6zm8 3H4v1h8V9z\" } }, { \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M1 4l1-1h12l1 1v8l-1 1H2l-1-1V4zm1 0v8h12V4H2z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-check\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M14.431 3.323l-8.47 10-.79-.036-3.35-4.77.818-.574 2.978 4.24 8.051-9.506.764.646z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-close\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M8 8.707l3.646 3.647.708-.707L8.707 8l3.647-3.646-.707-.708L8 7.293 4.354 3.646l-.707.708L7.293 8l-3.646 3.646.707.708L8 8.707z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-pass\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"d\": \"M6.27 10.87h.71l4.56-4.56-.71-.71-4.2 4.21-1.92-1.92L4 8.6l2.27 2.27z\" } }, { \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M8.6 1c1.6.1 3.1.9 4.2 2 1.3 1.4 2 3.1 2 5.1 0 1.6-.6 3.1-1.6 4.4-1 1.2-2.4 2.1-4 2.4-1.6.3-3.2.1-4.6-.7-1.4-.8-2.5-2-3.1-3.5C.9 9.2.8 7.5 1.3 6c.5-1.6 1.4-2.9 2.8-3.8C5.4 1.3 7 .9 8.6 1zm.5 12.9c1.3-.3 2.5-1 3.4-2.1.8-1.1 1.3-2.4 1.2-3.8 0-1.6-.6-3.2-1.7-4.3-1-1-2.2-1.6-3.6-1.7-1.3-.1-2.7.2-3.8 1-1.1.8-1.9 1.9-2.3 3.3-.4 1.3-.4 2.7.2 4 .6 1.3 1.5 2.3 2.7 3 1.2.7 2.6.9 3.9.6z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-gist\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M10.57 1.14l3.28 3.3.15.36v9.7l-.5.5h-11l-.5-.5v-13l.5-.5h7.72l.35.14zM10 5h3l-3-3v3zM3 2v12h10V6H9.5L9 5.5V2H3zm2.062 7.533l1.817-1.828L6.17 7 4 9.179v.707l2.171 2.174.707-.707-1.816-1.82zM8.8 7.714l.7-.709 2.189 2.175v.709L9.5 12.062l-.705-.709 1.831-1.82L8.8 7.714z\" } }] }] }] };\nvar clipPaths_default = svgJson;\n\n// packages/playwright-core/src/server/injected/recorder/recorder.ts\nvar NoneTool = class {\n cursor() {\n return \"default\";\n }\n};\nvar InspectTool = class {\n constructor(recorder, assertVisibility) {\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._hoveredSelectors = null;\n this._recorder = recorder;\n this._assertVisibility = assertVisibility;\n }\n cursor() {\n return \"pointer\";\n }\n cleanup() {\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._hoveredSelectors = null;\n }\n onClick(event) {\n var _a;\n consumeEvent(event);\n if (event.button !== 0)\n return;\n if ((_a = this._hoveredModel) == null ? void 0 : _a.selector)\n this._commit(this._hoveredModel.selector, this._hoveredModel);\n }\n onContextMenu(event) {\n if (this._hoveredModel && !this._hoveredModel.tooltipListItemSelected && this._hoveredSelectors && this._hoveredSelectors.length > 1) {\n consumeEvent(event);\n const selectors = this._hoveredSelectors;\n const hoveredModel = this._hoveredModel;\n this._hoveredModel.tooltipFooter = void 0;\n this._hoveredModel.tooltipList = selectors.map((selector) => this._recorder.injectedScript.utils.asLocator(this._recorder.state.language, selector));\n this._hoveredModel.tooltipListItemSelected = (index) => {\n if (index === void 0)\n this._reset(true);\n else\n this._commit(selectors[index], hoveredModel);\n };\n this._recorder.updateHighlight(this._hoveredModel, true);\n }\n }\n onPointerDown(event) {\n consumeEvent(event);\n }\n onPointerUp(event) {\n consumeEvent(event);\n }\n onMouseDown(event) {\n consumeEvent(event);\n }\n onMouseUp(event) {\n consumeEvent(event);\n }\n onMouseMove(event) {\n var _a;\n consumeEvent(event);\n let target = this._recorder.deepEventTarget(event);\n if (!target.isConnected)\n target = null;\n if (this._hoveredElement === target)\n return;\n this._hoveredElement = target;\n let model = null;\n let selectors = [];\n if (this._hoveredElement) {\n const generated = this._recorder.injectedScript.generateSelector(this._hoveredElement, { testIdAttributeName: this._recorder.state.testIdAttributeName, multiple: false });\n selectors = generated.selectors;\n model = {\n selector: generated.selector,\n elements: generated.elements,\n tooltipText: this._recorder.injectedScript.utils.asLocator(this._recorder.state.language, generated.selector),\n tooltipFooter: selectors.length > 1 ? `Click to select, right-click for more options` : void 0,\n color: this._assertVisibility ? \"#8acae480\" : void 0\n };\n }\n if (((_a = this._hoveredModel) == null ? void 0 : _a.selector) === (model == null ? void 0 : model.selector))\n return;\n this._hoveredModel = model;\n this._hoveredSelectors = selectors;\n this._recorder.updateHighlight(model, true);\n }\n onMouseEnter(event) {\n consumeEvent(event);\n }\n onMouseLeave(event) {\n consumeEvent(event);\n const window = this._recorder.injectedScript.window;\n if (window.top !== window && this._recorder.deepEventTarget(event).nodeType === Node.DOCUMENT_NODE)\n this._reset(true);\n }\n onKeyDown(event) {\n var _a;\n consumeEvent(event);\n if (event.key === \"Escape\") {\n if ((_a = this._hoveredModel) == null ? void 0 : _a.tooltipListItemSelected)\n this._reset(true);\n else if (this._assertVisibility)\n this._recorder.setMode(\"recording\");\n }\n }\n onKeyUp(event) {\n consumeEvent(event);\n }\n onScroll(event) {\n this._reset(false);\n }\n _commit(selector, model) {\n var _a;\n if (this._assertVisibility) {\n this._recorder.recordAction({\n name: \"assertVisible\",\n selector,\n signals: []\n });\n this._recorder.setMode(\"recording\");\n (_a = this._recorder.overlay) == null ? void 0 : _a.flashToolSucceeded(\"assertingVisibility\");\n } else {\n this._recorder.elementPicked(selector, model);\n }\n }\n _reset(userGesture) {\n this._hoveredElement = null;\n this._hoveredModel = null;\n this._hoveredSelectors = null;\n this._recorder.updateHighlight(null, userGesture);\n }\n};\nvar RecordActionTool = class {\n constructor(recorder) {\n this._performingActions = /* @__PURE__ */ new Set();\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._activeModel = null;\n this._expectProgrammaticKeyUp = false;\n this._recorder = recorder;\n }\n cursor() {\n return \"pointer\";\n }\n cleanup() {\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._activeModel = null;\n this._expectProgrammaticKeyUp = false;\n }\n onClick(event) {\n if (isRangeInput(this._hoveredElement))\n return;\n if (event.button === 2 && event.type === \"auxclick\")\n return;\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (this._actionInProgress(event))\n return;\n if (this._consumedDueToNoModel(event, this._hoveredModel))\n return;\n const checkbox = asCheckbox(this._recorder.deepEventTarget(event));\n if (checkbox) {\n this._performAction({\n name: checkbox.checked ? \"check\" : \"uncheck\",\n selector: this._hoveredModel.selector,\n signals: []\n });\n return;\n }\n this._cancelPendingClickAction();\n if (event.detail === 1) {\n this._pendingClickAction = {\n action: {\n name: \"click\",\n selector: this._hoveredModel.selector,\n position: positionForEvent(event),\n signals: [],\n button: buttonForEvent(event),\n modifiers: modifiersForEvent(event),\n clickCount: event.detail\n },\n timeout: this._recorder.injectedScript.builtinSetTimeout(() => this._commitPendingClickAction(), 200)\n };\n }\n }\n onDblClick(event) {\n if (isRangeInput(this._hoveredElement))\n return;\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (this._actionInProgress(event))\n return;\n if (this._consumedDueToNoModel(event, this._hoveredModel))\n return;\n this._cancelPendingClickAction();\n this._performAction({\n name: \"click\",\n selector: this._hoveredModel.selector,\n position: positionForEvent(event),\n signals: [],\n button: buttonForEvent(event),\n modifiers: modifiersForEvent(event),\n clickCount: event.detail\n });\n }\n _commitPendingClickAction() {\n if (this._pendingClickAction)\n this._performAction(this._pendingClickAction.action);\n this._cancelPendingClickAction();\n }\n _cancelPendingClickAction() {\n if (this._pendingClickAction)\n clearTimeout(this._pendingClickAction.timeout);\n this._pendingClickAction = void 0;\n }\n onContextMenu(event) {\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (this._actionInProgress(event))\n return;\n if (this._consumedDueToNoModel(event, this._hoveredModel))\n return;\n this._performAction({\n name: \"click\",\n selector: this._hoveredModel.selector,\n position: positionForEvent(event),\n signals: [],\n button: \"right\",\n modifiers: 0,\n clickCount: 0\n });\n }\n onPointerDown(event) {\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (!this._performingActions.size)\n consumeEvent(event);\n }\n onPointerUp(event) {\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (!this._performingActions.size)\n consumeEvent(event);\n }\n onMouseDown(event) {\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (!this._performingActions.size)\n consumeEvent(event);\n this._activeModel = this._hoveredModel;\n }\n onMouseUp(event) {\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (!this._performingActions.size)\n consumeEvent(event);\n }\n onMouseMove(event) {\n const target = this._recorder.deepEventTarget(event);\n if (this._hoveredElement === target)\n return;\n this._hoveredElement = target;\n this._updateModelForHoveredElement();\n }\n onMouseLeave(event) {\n const window = this._recorder.injectedScript.window;\n if (window.top !== window && this._recorder.deepEventTarget(event).nodeType === Node.DOCUMENT_NODE) {\n this._hoveredElement = null;\n this._updateModelForHoveredElement();\n }\n }\n onFocus(event) {\n this._onFocus(true);\n }\n onInput(event) {\n const target = this._recorder.deepEventTarget(event);\n if (target.nodeName === \"INPUT\" && target.type.toLowerCase() === \"file\") {\n this._recorder.recordAction({\n name: \"setInputFiles\",\n selector: this._activeModel.selector,\n signals: [],\n files: [...target.files || []].map((file) => file.name)\n });\n return;\n }\n if (isRangeInput(target)) {\n this._recorder.recordAction({\n name: \"fill\",\n // must use hoveredModel instead of activeModel for it to work in webkit\n selector: this._hoveredModel.selector,\n signals: [],\n text: target.value\n });\n return;\n }\n if ([\"INPUT\", \"TEXTAREA\"].includes(target.nodeName) || target.isContentEditable) {\n if (target.nodeName === \"INPUT\" && [\"checkbox\", \"radio\"].includes(target.type.toLowerCase())) {\n return;\n }\n if (this._consumedDueWrongTarget(event))\n return;\n this._recorder.recordAction({\n name: \"fill\",\n selector: this._activeModel.selector,\n signals: [],\n text: target.isContentEditable ? target.innerText : target.value\n });\n }\n if (target.nodeName === \"SELECT\") {\n const selectElement = target;\n if (this._actionInProgress(event))\n return;\n this._performAction({\n name: \"select\",\n selector: this._activeModel.selector,\n options: [...selectElement.selectedOptions].map((option) => option.value),\n signals: []\n });\n }\n }\n onKeyDown(event) {\n if (!this._shouldGenerateKeyPressFor(event))\n return;\n if (this._actionInProgress(event)) {\n this._expectProgrammaticKeyUp = true;\n return;\n }\n if (this._consumedDueWrongTarget(event))\n return;\n if (event.key === \" \") {\n const checkbox = asCheckbox(this._recorder.deepEventTarget(event));\n if (checkbox) {\n this._performAction({\n name: checkbox.checked ? \"uncheck\" : \"check\",\n selector: this._activeModel.selector,\n signals: []\n });\n return;\n }\n }\n this._performAction({\n name: \"press\",\n selector: this._activeModel.selector,\n signals: [],\n key: event.key,\n modifiers: modifiersForEvent(event)\n });\n }\n onKeyUp(event) {\n if (!this._shouldGenerateKeyPressFor(event))\n return;\n if (!this._expectProgrammaticKeyUp) {\n consumeEvent(event);\n return;\n }\n this._expectProgrammaticKeyUp = false;\n }\n onScroll(event) {\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._recorder.updateHighlight(null, false);\n }\n _onFocus(userGesture) {\n const activeElement = deepActiveElement(this._recorder.document);\n if (userGesture && activeElement === this._recorder.document.body)\n return;\n const result = activeElement ? this._recorder.injectedScript.generateSelector(activeElement, { testIdAttributeName: this._recorder.state.testIdAttributeName }) : null;\n this._activeModel = result && result.selector ? result : null;\n if (userGesture)\n this._hoveredElement = activeElement;\n this._updateModelForHoveredElement();\n }\n _shouldIgnoreMouseEvent(event) {\n const target = this._recorder.deepEventTarget(event);\n const nodeName = target.nodeName;\n if (nodeName === \"SELECT\" || nodeName === \"OPTION\")\n return true;\n if (nodeName === \"INPUT\" && [\"date\", \"range\"].includes(target.type))\n return true;\n return false;\n }\n _actionInProgress(event) {\n const isKeyEvent = event instanceof KeyboardEvent;\n const isMouseOrPointerEvent = event instanceof MouseEvent || event instanceof PointerEvent;\n for (const action of this._performingActions) {\n if (isKeyEvent && action.name === \"press\" && event.key === action.key)\n return true;\n if (isMouseOrPointerEvent && (action.name === \"click\" || action.name === \"check\" || action.name === \"uncheck\"))\n return true;\n }\n consumeEvent(event);\n return false;\n }\n _consumedDueToNoModel(event, model) {\n if (model)\n return false;\n consumeEvent(event);\n return true;\n }\n _consumedDueWrongTarget(event) {\n if (this._activeModel && this._activeModel.elements[0] === this._recorder.deepEventTarget(event))\n return false;\n consumeEvent(event);\n return true;\n }\n _performAction(action) {\n this._hoveredElement = null;\n this._hoveredModel = null;\n this._activeModel = null;\n this._recorder.updateHighlight(null, false);\n this._performingActions.add(action);\n void this._recorder.performAction(action).then(() => {\n this._performingActions.delete(action);\n this._onFocus(false);\n if (this._recorder.injectedScript.isUnderTest) {\n console.error(\"Action performed for test: \" + JSON.stringify({\n // eslint-disable-line no-console\n hovered: this._hoveredModel ? this._hoveredModel.selector : null,\n active: this._activeModel ? this._activeModel.selector : null\n }));\n }\n });\n }\n _shouldGenerateKeyPressFor(event) {\n if (event.key === \"Enter\" && (this._recorder.deepEventTarget(event).nodeName === \"TEXTAREA\" || this._recorder.deepEventTarget(event).isContentEditable))\n return false;\n if ([\"Backspace\", \"Delete\", \"AltGraph\"].includes(event.key))\n return false;\n if (event.key === \"@\" && event.code === \"KeyL\")\n return false;\n if (navigator.platform.includes(\"Mac\")) {\n if (event.key === \"v\" && event.metaKey)\n return false;\n } else {\n if (event.key === \"v\" && event.ctrlKey)\n return false;\n if (event.key === \"Insert\" && event.shiftKey)\n return false;\n }\n if ([\"Shift\", \"Control\", \"Meta\", \"Alt\", \"Process\"].includes(event.key))\n return false;\n const hasModifier = event.ctrlKey || event.altKey || event.metaKey;\n if (event.key.length === 1 && !hasModifier)\n return !!asCheckbox(this._recorder.deepEventTarget(event));\n return true;\n }\n _updateModelForHoveredElement() {\n if (!this._hoveredElement || !this._hoveredElement.isConnected) {\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._recorder.updateHighlight(null, true);\n return;\n }\n const { selector, elements } = this._recorder.injectedScript.generateSelector(this._hoveredElement, { testIdAttributeName: this._recorder.state.testIdAttributeName });\n if (this._hoveredModel && this._hoveredModel.selector === selector)\n return;\n this._hoveredModel = selector ? { selector, elements, color: \"#dc6f6f7f\" } : null;\n this._recorder.updateHighlight(this._hoveredModel, true);\n }\n};\nvar TextAssertionTool = class {\n constructor(recorder, kind) {\n this._hoverHighlight = null;\n this._action = null;\n this._textCache = /* @__PURE__ */ new Map();\n this._recorder = recorder;\n this._kind = kind;\n this._dialog = new Dialog(recorder);\n }\n cursor() {\n return \"pointer\";\n }\n cleanup() {\n this._dialog.close();\n this._hoverHighlight = null;\n }\n onClick(event) {\n consumeEvent(event);\n if (this._kind === \"value\") {\n this._commitAssertValue();\n } else {\n if (!this._dialog.isShowing())\n this._showDialog();\n }\n }\n onMouseDown(event) {\n const target = this._recorder.deepEventTarget(event);\n if (this._elementHasValue(target))\n event.preventDefault();\n }\n onPointerUp(event) {\n var _a;\n const target = (_a = this._hoverHighlight) == null ? void 0 : _a.elements[0];\n if (this._kind === \"value\" && target && (target.nodeName === \"INPUT\" || target.nodeName === \"SELECT\") && target.disabled) {\n this._commitAssertValue();\n }\n }\n onMouseMove(event) {\n var _a;\n if (this._dialog.isShowing())\n return;\n const target = this._recorder.deepEventTarget(event);\n if (((_a = this._hoverHighlight) == null ? void 0 : _a.elements[0]) === target)\n return;\n if (this._kind === \"text\" || this._kind === \"snapshot\")\n this._hoverHighlight = this._recorder.injectedScript.utils.elementText(this._textCache, target).full ? { elements: [target], selector: \"\" } : null;\n else\n this._hoverHighlight = this._elementHasValue(target) ? this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName }) : null;\n if (this._hoverHighlight)\n this._hoverHighlight.color = \"#8acae480\";\n this._recorder.updateHighlight(this._hoverHighlight, true);\n }\n onKeyDown(event) {\n if (event.key === \"Escape\")\n this._recorder.setMode(\"recording\");\n consumeEvent(event);\n }\n onScroll(event) {\n this._recorder.updateHighlight(this._hoverHighlight, false);\n }\n _elementHasValue(element) {\n return element.nodeName === \"TEXTAREA\" || element.nodeName === \"SELECT\" || element.nodeName === \"INPUT\" && ![\"button\", \"image\", \"reset\", \"submit\"].includes(element.type);\n }\n _generateAction() {\n var _a;\n this._textCache.clear();\n const target = (_a = this._hoverHighlight) == null ? void 0 : _a.elements[0];\n if (!target)\n return null;\n if (this._kind === \"value\") {\n if (!this._elementHasValue(target))\n return null;\n const { selector } = this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName });\n if (target.nodeName === \"INPUT\" && [\"checkbox\", \"radio\"].includes(target.type.toLowerCase())) {\n return {\n name: \"assertChecked\",\n selector,\n signals: [],\n // Interestingly, inputElement.checked is reversed inside this event handler.\n checked: !target.checked\n };\n } else {\n return {\n name: \"assertValue\",\n selector,\n signals: [],\n value: target.value\n };\n }\n } else if (this._kind === \"snapshot\") {\n this._hoverHighlight = this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName, forTextExpect: true });\n this._hoverHighlight.color = \"#8acae480\";\n this._recorder.updateHighlight(this._hoverHighlight, true);\n return {\n name: \"assertSnapshot\",\n selector: this._hoverHighlight.selector,\n signals: [],\n snapshot: this._recorder.injectedScript.ariaSnapshot(target, { mode: \"regex\" })\n };\n } else {\n this._hoverHighlight = this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName, forTextExpect: true });\n this._hoverHighlight.color = \"#8acae480\";\n this._recorder.updateHighlight(this._hoverHighlight, true);\n return {\n name: \"assertText\",\n selector: this._hoverHighlight.selector,\n signals: [],\n text: this._recorder.injectedScript.utils.elementText(this._textCache, target).normalized,\n substring: true\n };\n }\n }\n _renderValue(action) {\n if ((action == null ? void 0 : action.name) === \"assertText\")\n return this._recorder.injectedScript.utils.normalizeWhiteSpace(action.text);\n if ((action == null ? void 0 : action.name) === \"assertChecked\")\n return String(action.checked);\n if ((action == null ? void 0 : action.name) === \"assertValue\")\n return action.value;\n if ((action == null ? void 0 : action.name) === \"assertSnapshot\")\n return action.snapshot;\n return \"\";\n }\n _commit() {\n if (!this._action || !this._dialog.isShowing())\n return;\n this._dialog.close();\n this._recorder.recordAction(this._action);\n this._recorder.setMode(\"recording\");\n }\n _showDialog() {\n var _a, _b, _c, _d;\n if (!((_a = this._hoverHighlight) == null ? void 0 : _a.elements[0]))\n return;\n this._action = this._generateAction();\n if (((_b = this._action) == null ? void 0 : _b.name) === \"assertText\") {\n this._showTextDialog(this._action);\n } else if (((_c = this._action) == null ? void 0 : _c.name) === \"assertSnapshot\") {\n this._recorder.recordAction(this._action);\n this._recorder.setMode(\"recording\");\n (_d = this._recorder.overlay) == null ? void 0 : _d.flashToolSucceeded(\"assertingSnapshot\");\n }\n }\n _showTextDialog(action) {\n const textElement = this._recorder.document.createElement(\"textarea\");\n textElement.setAttribute(\"spellcheck\", \"false\");\n textElement.value = this._renderValue(action);\n textElement.classList.add(\"text-editor\");\n const updateAndValidate = () => {\n var _a;\n const newValue = this._recorder.injectedScript.utils.normalizeWhiteSpace(textElement.value);\n const target = (_a = this._hoverHighlight) == null ? void 0 : _a.elements[0];\n if (!target)\n return;\n action.text = newValue;\n const targetText = this._recorder.injectedScript.utils.elementText(this._textCache, target).normalized;\n const matches = newValue && targetText.includes(newValue);\n textElement.classList.toggle(\"does-not-match\", !matches);\n };\n textElement.addEventListener(\"input\", updateAndValidate);\n const label = \"Assert that element contains text\";\n const dialogElement = this._dialog.show({\n label,\n body: textElement,\n onCommit: () => this._commit()\n });\n const position = this._recorder.highlight.tooltipPosition(this._recorder.highlight.firstBox(), dialogElement);\n this._dialog.moveTo(position.anchorTop, position.anchorLeft);\n textElement.focus();\n }\n _commitAssertValue() {\n var _a;\n if (this._kind !== \"value\")\n return;\n const action = this._generateAction();\n if (!action)\n return;\n this._recorder.recordAction(action);\n this._recorder.setMode(\"recording\");\n (_a = this._recorder.overlay) == null ? void 0 : _a.flashToolSucceeded(\"assertingValue\");\n }\n};\nvar Overlay = class {\n constructor(recorder) {\n this._listeners = [];\n this._offsetX = 0;\n this._measure = { width: 0, height: 0 };\n this._recorder = recorder;\n const document = this._recorder.document;\n this._overlayElement = document.createElement(\"x-pw-overlay\");\n const toolsListElement = document.createElement(\"x-pw-tools-list\");\n this._overlayElement.appendChild(toolsListElement);\n this._dragHandle = document.createElement(\"x-pw-tool-gripper\");\n this._dragHandle.appendChild(document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._dragHandle);\n this._recordToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._recordToggle.title = \"Record\";\n this._recordToggle.classList.add(\"record\");\n this._recordToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._recordToggle);\n this._pickLocatorToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._pickLocatorToggle.title = \"Pick locator\";\n this._pickLocatorToggle.classList.add(\"pick-locator\");\n this._pickLocatorToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._pickLocatorToggle);\n this._assertVisibilityToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._assertVisibilityToggle.title = \"Assert visibility\";\n this._assertVisibilityToggle.classList.add(\"visibility\");\n this._assertVisibilityToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._assertVisibilityToggle);\n this._assertTextToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._assertTextToggle.title = \"Assert text\";\n this._assertTextToggle.classList.add(\"text\");\n this._assertTextToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._assertTextToggle);\n this._assertValuesToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._assertValuesToggle.title = \"Assert value\";\n this._assertValuesToggle.classList.add(\"value\");\n this._assertValuesToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._assertValuesToggle);\n this._assertSnapshotToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._assertSnapshotToggle.title = \"Assert snapshot\";\n this._assertSnapshotToggle.classList.add(\"snapshot\");\n this._assertSnapshotToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._assertSnapshotToggle);\n this._updateVisualPosition();\n this._refreshListeners();\n }\n _refreshListeners() {\n removeEventListeners(this._listeners);\n this._listeners = [\n addEventListener(this._dragHandle, \"mousedown\", (event) => {\n this._dragState = { offsetX: this._offsetX, dragStart: { x: event.clientX, y: 0 } };\n }),\n addEventListener(this._recordToggle, \"click\", () => {\n this._recorder.setMode(this._recorder.state.mode === \"none\" || this._recorder.state.mode === \"standby\" || this._recorder.state.mode === \"inspecting\" ? \"recording\" : \"standby\");\n }),\n addEventListener(this._pickLocatorToggle, \"click\", () => {\n const newMode = {\n \"inspecting\": \"standby\",\n \"none\": \"inspecting\",\n \"standby\": \"inspecting\",\n \"recording\": \"recording-inspecting\",\n \"recording-inspecting\": \"recording\",\n \"assertingText\": \"recording-inspecting\",\n \"assertingVisibility\": \"recording-inspecting\",\n \"assertingValue\": \"recording-inspecting\",\n \"assertingSnapshot\": \"recording-inspecting\"\n };\n this._recorder.setMode(newMode[this._recorder.state.mode]);\n }),\n addEventListener(this._assertVisibilityToggle, \"click\", () => {\n if (!this._assertVisibilityToggle.classList.contains(\"disabled\"))\n this._recorder.setMode(this._recorder.state.mode === \"assertingVisibility\" ? \"recording\" : \"assertingVisibility\");\n }),\n addEventListener(this._assertTextToggle, \"click\", () => {\n if (!this._assertTextToggle.classList.contains(\"disabled\"))\n this._recorder.setMode(this._recorder.state.mode === \"assertingText\" ? \"recording\" : \"assertingText\");\n }),\n addEventListener(this._assertValuesToggle, \"click\", () => {\n if (!this._assertValuesToggle.classList.contains(\"disabled\"))\n this._recorder.setMode(this._recorder.state.mode === \"assertingValue\" ? \"recording\" : \"assertingValue\");\n }),\n addEventListener(this._assertSnapshotToggle, \"click\", () => {\n if (!this._assertSnapshotToggle.classList.contains(\"disabled\"))\n this._recorder.setMode(this._recorder.state.mode === \"assertingSnapshot\" ? \"recording\" : \"assertingSnapshot\");\n })\n ];\n }\n install() {\n this._recorder.highlight.appendChild(this._overlayElement);\n this._refreshListeners();\n this._updateVisualPosition();\n }\n contains(element) {\n return this._recorder.injectedScript.utils.isInsideScope(this._overlayElement, element);\n }\n setUIState(state) {\n this._recordToggle.classList.toggle(\"active\", state.mode === \"recording\" || state.mode === \"assertingText\" || state.mode === \"assertingVisibility\" || state.mode === \"assertingValue\" || state.mode === \"recording-inspecting\");\n this._pickLocatorToggle.classList.toggle(\"active\", state.mode === \"inspecting\" || state.mode === \"recording-inspecting\");\n this._assertVisibilityToggle.classList.toggle(\"active\", state.mode === \"assertingVisibility\");\n this._assertVisibilityToggle.classList.toggle(\"disabled\", state.mode === \"none\" || state.mode === \"standby\" || state.mode === \"inspecting\");\n this._assertTextToggle.classList.toggle(\"active\", state.mode === \"assertingText\");\n this._assertTextToggle.classList.toggle(\"disabled\", state.mode === \"none\" || state.mode === \"standby\" || state.mode === \"inspecting\");\n this._assertValuesToggle.classList.toggle(\"active\", state.mode === \"assertingValue\");\n this._assertValuesToggle.classList.toggle(\"disabled\", state.mode === \"none\" || state.mode === \"standby\" || state.mode === \"inspecting\");\n this._assertSnapshotToggle.classList.toggle(\"active\", state.mode === \"assertingSnapshot\");\n this._assertSnapshotToggle.classList.toggle(\"disabled\", state.mode === \"none\" || state.mode === \"standby\" || state.mode === \"inspecting\");\n if (this._offsetX !== state.overlay.offsetX) {\n this._offsetX = state.overlay.offsetX;\n this._updateVisualPosition();\n }\n if (state.mode === \"none\")\n this._hideOverlay();\n else\n this._showOverlay();\n }\n flashToolSucceeded(tool) {\n let element;\n if (tool === \"assertingVisibility\")\n element = this._assertVisibilityToggle;\n else if (tool === \"assertingSnapshot\")\n element = this._assertSnapshotToggle;\n else\n element = this._assertValuesToggle;\n element.classList.add(\"succeeded\");\n this._recorder.injectedScript.builtinSetTimeout(() => element.classList.remove(\"succeeded\"), 2e3);\n }\n _hideOverlay() {\n this._overlayElement.setAttribute(\"hidden\", \"true\");\n }\n _showOverlay() {\n if (!this._overlayElement.hasAttribute(\"hidden\"))\n return;\n this._overlayElement.removeAttribute(\"hidden\");\n this._updateVisualPosition();\n }\n _updateVisualPosition() {\n this._measure = this._overlayElement.getBoundingClientRect();\n this._overlayElement.style.left = (this._recorder.injectedScript.window.innerWidth - this._measure.width) / 2 + this._offsetX + \"px\";\n }\n onMouseMove(event) {\n if (!event.buttons) {\n this._dragState = void 0;\n return false;\n }\n if (this._dragState) {\n this._offsetX = this._dragState.offsetX + event.clientX - this._dragState.dragStart.x;\n const halfGapSize = (this._recorder.injectedScript.window.innerWidth - this._measure.width) / 2 - 10;\n this._offsetX = Math.max(-halfGapSize, Math.min(halfGapSize, this._offsetX));\n this._updateVisualPosition();\n this._recorder.setOverlayState({ offsetX: this._offsetX });\n consumeEvent(event);\n return true;\n }\n return false;\n }\n onMouseUp(event) {\n if (this._dragState) {\n consumeEvent(event);\n return true;\n }\n return false;\n }\n onClick(event) {\n if (this._dragState) {\n this._dragState = void 0;\n consumeEvent(event);\n return true;\n }\n return false;\n }\n onDblClick(event) {\n return false;\n }\n};\nvar Recorder = class {\n constructor(injectedScript) {\n this._listeners = [];\n this._actionSelectorModel = null;\n this._lastHighlightedAriaTemplateJSON = \"undefined\";\n this.state = {\n mode: \"none\",\n testIdAttributeName: \"data-testid\",\n language: \"javascript\",\n overlay: { offsetX: 0 }\n };\n this._delegate = {};\n this.document = injectedScript.document;\n this.injectedScript = injectedScript;\n this.highlight = injectedScript.createHighlight();\n this._tools = {\n \"none\": new NoneTool(),\n \"standby\": new NoneTool(),\n \"inspecting\": new InspectTool(this, false),\n \"recording\": new RecordActionTool(this),\n \"recording-inspecting\": new InspectTool(this, false),\n \"assertingText\": new TextAssertionTool(this, \"text\"),\n \"assertingVisibility\": new InspectTool(this, true),\n \"assertingValue\": new TextAssertionTool(this, \"value\"),\n \"assertingSnapshot\": new TextAssertionTool(this, \"snapshot\")\n };\n this._currentTool = this._tools.none;\n if (injectedScript.window.top === injectedScript.window) {\n this.overlay = new Overlay(this);\n this.overlay.setUIState(this.state);\n }\n this._stylesheet = new injectedScript.window.CSSStyleSheet();\n this._stylesheet.replaceSync(`\n body[data-pw-cursor=pointer] *, body[data-pw-cursor=pointer] *::after { cursor: pointer !important; }\n body[data-pw-cursor=text] *, body[data-pw-cursor=text] *::after { cursor: text !important; }\n `);\n this.installListeners();\n injectedScript.utils.cacheNormalizedWhitespaces();\n if (injectedScript.isUnderTest)\n console.error(\"Recorder script ready for test\");\n }\n installListeners() {\n var _a;\n removeEventListeners(this._listeners);\n this._listeners = [\n addEventListener(this.document, \"click\", (event) => this._onClick(event), true),\n addEventListener(this.document, \"auxclick\", (event) => this._onClick(event), true),\n addEventListener(this.document, \"dblclick\", (event) => this._onDblClick(event), true),\n addEventListener(this.document, \"contextmenu\", (event) => this._onContextMenu(event), true),\n addEventListener(this.document, \"dragstart\", (event) => this._onDragStart(event), true),\n addEventListener(this.document, \"input\", (event) => this._onInput(event), true),\n addEventListener(this.document, \"keydown\", (event) => this._onKeyDown(event), true),\n addEventListener(this.document, \"keyup\", (event) => this._onKeyUp(event), true),\n addEventListener(this.document, \"pointerdown\", (event) => this._onPointerDown(event), true),\n addEventListener(this.document, \"pointerup\", (event) => this._onPointerUp(event), true),\n addEventListener(this.document, \"mousedown\", (event) => this._onMouseDown(event), true),\n addEventListener(this.document, \"mouseup\", (event) => this._onMouseUp(event), true),\n addEventListener(this.document, \"mousemove\", (event) => this._onMouseMove(event), true),\n addEventListener(this.document, \"mouseleave\", (event) => this._onMouseLeave(event), true),\n addEventListener(this.document, \"mouseenter\", (event) => this._onMouseEnter(event), true),\n addEventListener(this.document, \"focus\", (event) => this._onFocus(event), true),\n addEventListener(this.document, \"scroll\", (event) => this._onScroll(event), true)\n ];\n this.highlight.install();\n let recreationInterval;\n const recreate = () => {\n this.highlight.install();\n recreationInterval = this.injectedScript.builtinSetTimeout(recreate, 500);\n };\n recreationInterval = this.injectedScript.builtinSetTimeout(recreate, 500);\n this._listeners.push(() => this.injectedScript.builtinClearTimeout(recreationInterval));\n this.highlight.appendChild(createSvgElement(this.document, clipPaths_default));\n (_a = this.overlay) == null ? void 0 : _a.install();\n this.document.adoptedStyleSheets.push(this._stylesheet);\n }\n _switchCurrentTool() {\n var _a, _b, _c;\n const newTool = this._tools[this.state.mode];\n if (newTool === this._currentTool)\n return;\n (_b = (_a = this._currentTool).cleanup) == null ? void 0 : _b.call(_a);\n this.clearHighlight();\n this._currentTool = newTool;\n (_c = this.injectedScript.document.body) == null ? void 0 : _c.setAttribute(\"data-pw-cursor\", newTool.cursor());\n }\n setUIState(state, delegate) {\n var _a, _b, _c, _d;\n this._delegate = delegate;\n if (state.actionPoint && this.state.actionPoint && state.actionPoint.x === this.state.actionPoint.x && state.actionPoint.y === this.state.actionPoint.y) {\n } else if (!state.actionPoint && !this.state.actionPoint) {\n } else {\n if (state.actionPoint)\n this.highlight.showActionPoint(state.actionPoint.x, state.actionPoint.y);\n else\n this.highlight.hideActionPoint();\n }\n this.state = state;\n this.highlight.setLanguage(state.language);\n this._switchCurrentTool();\n (_a = this.overlay) == null ? void 0 : _a.setUIState(state);\n if (((_b = this._actionSelectorModel) == null ? void 0 : _b.selector) && !((_c = this._actionSelectorModel) == null ? void 0 : _c.elements.length) && !this._lastHighlightedAriaTemplateJSON)\n this._actionSelectorModel = null;\n if (state.actionSelector && state.actionSelector !== ((_d = this._actionSelectorModel) == null ? void 0 : _d.selector))\n this._actionSelectorModel = querySelector(this.injectedScript, state.actionSelector, this.document);\n const ariaTemplateJSON = JSON.stringify(state.ariaTemplate);\n if (this._lastHighlightedAriaTemplateJSON !== ariaTemplateJSON) {\n this._lastHighlightedAriaTemplateJSON = ariaTemplateJSON;\n const template = state.ariaTemplate ? this.injectedScript.utils.parseYamlTemplate(state.ariaTemplate) : void 0;\n const elements = template ? this.injectedScript.getAllByAria(this.document, template) : [];\n if (elements.length)\n this._actionSelectorModel = { elements };\n else\n this._actionSelectorModel = null;\n }\n if (!state.actionSelector && !state.ariaTemplate)\n this._actionSelectorModel = null;\n if (this.state.mode === \"none\" || this.state.mode === \"standby\")\n this.updateHighlight(this._actionSelectorModel, false);\n }\n clearHighlight() {\n var _a, _b;\n (_b = (_a = this._currentTool).cleanup) == null ? void 0 : _b.call(_a);\n this.updateHighlight(null, false);\n }\n _onClick(event) {\n var _a, _b, _c;\n if (!event.isTrusted)\n return;\n if ((_a = this.overlay) == null ? void 0 : _a.onClick(event))\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_c = (_b = this._currentTool).onClick) == null ? void 0 : _c.call(_b, event);\n }\n _onDblClick(event) {\n var _a, _b, _c;\n if (!event.isTrusted)\n return;\n if ((_a = this.overlay) == null ? void 0 : _a.onDblClick(event))\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_c = (_b = this._currentTool).onDblClick) == null ? void 0 : _c.call(_b, event);\n }\n _onContextMenu(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onContextMenu) == null ? void 0 : _b.call(_a, event);\n }\n _onDragStart(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onDragStart) == null ? void 0 : _b.call(_a, event);\n }\n _onPointerDown(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onPointerDown) == null ? void 0 : _b.call(_a, event);\n }\n _onPointerUp(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onPointerUp) == null ? void 0 : _b.call(_a, event);\n }\n _onMouseDown(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onMouseDown) == null ? void 0 : _b.call(_a, event);\n }\n _onMouseUp(event) {\n var _a, _b, _c;\n if (!event.isTrusted)\n return;\n if ((_a = this.overlay) == null ? void 0 : _a.onMouseUp(event))\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_c = (_b = this._currentTool).onMouseUp) == null ? void 0 : _c.call(_b, event);\n }\n _onMouseMove(event) {\n var _a, _b, _c;\n if (!event.isTrusted)\n return;\n if ((_a = this.overlay) == null ? void 0 : _a.onMouseMove(event))\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_c = (_b = this._currentTool).onMouseMove) == null ? void 0 : _c.call(_b, event);\n }\n _onMouseEnter(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onMouseEnter) == null ? void 0 : _b.call(_a, event);\n }\n _onMouseLeave(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onMouseLeave) == null ? void 0 : _b.call(_a, event);\n }\n _onFocus(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onFocus) == null ? void 0 : _b.call(_a, event);\n }\n _onScroll(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n this.highlight.hideActionPoint();\n (_b = (_a = this._currentTool).onScroll) == null ? void 0 : _b.call(_a, event);\n }\n _onInput(event) {\n var _a, _b;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onInput) == null ? void 0 : _b.call(_a, event);\n }\n _onKeyDown(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onKeyDown) == null ? void 0 : _b.call(_a, event);\n }\n _onKeyUp(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onKeyUp) == null ? void 0 : _b.call(_a, event);\n }\n updateHighlight(model, userGesture) {\n var _a, _b;\n let tooltipText = model == null ? void 0 : model.tooltipText;\n if (tooltipText === void 0 && !(model == null ? void 0 : model.tooltipList) && (model == null ? void 0 : model.selector))\n tooltipText = this.injectedScript.utils.asLocator(this.state.language, model.selector);\n this.highlight.updateHighlight((model == null ? void 0 : model.elements) || [], { ...model, tooltipText });\n if (userGesture)\n (_b = (_a = this._delegate).highlightUpdated) == null ? void 0 : _b.call(_a);\n }\n _ignoreOverlayEvent(event) {\n return event.composedPath().some((e) => {\n const nodeName = e.nodeName || \"\";\n return nodeName.toLowerCase() === \"x-pw-glass\";\n });\n }\n deepEventTarget(event) {\n var _a;\n for (const element of event.composedPath()) {\n if (!((_a = this.overlay) == null ? void 0 : _a.contains(element)))\n return element;\n }\n return event.composedPath()[0];\n }\n setMode(mode) {\n var _a, _b;\n void ((_b = (_a = this._delegate).setMode) == null ? void 0 : _b.call(_a, mode));\n }\n async performAction(action) {\n var _a, _b;\n await ((_b = (_a = this._delegate).performAction) == null ? void 0 : _b.call(_a, action).catch(() => {\n }));\n }\n recordAction(action) {\n var _a, _b;\n void ((_b = (_a = this._delegate).recordAction) == null ? void 0 : _b.call(_a, action));\n }\n setOverlayState(state) {\n var _a, _b;\n void ((_b = (_a = this._delegate).setOverlayState) == null ? void 0 : _b.call(_a, state));\n }\n elementPicked(selector, model) {\n var _a, _b;\n const ariaSnapshot = this.injectedScript.ariaSnapshot(model.elements[0]);\n void ((_b = (_a = this._delegate).elementPicked) == null ? void 0 : _b.call(_a, { selector, ariaSnapshot }));\n }\n};\nvar Dialog = class {\n constructor(recorder) {\n this._dialogElement = null;\n this._recorder = recorder;\n }\n isShowing() {\n return !!this._dialogElement;\n }\n show(options) {\n const acceptButton = this._recorder.document.createElement(\"x-pw-tool-item\");\n acceptButton.title = \"Accept\";\n acceptButton.classList.add(\"accept\");\n acceptButton.appendChild(this._recorder.document.createElement(\"x-div\"));\n acceptButton.addEventListener(\"click\", () => options.onCommit());\n const cancelButton = this._recorder.document.createElement(\"x-pw-tool-item\");\n cancelButton.title = \"Close\";\n cancelButton.classList.add(\"cancel\");\n cancelButton.appendChild(this._recorder.document.createElement(\"x-div\"));\n cancelButton.addEventListener(\"click\", () => {\n var _a;\n this.close();\n (_a = options.onCancel) == null ? void 0 : _a.call(options);\n });\n this._dialogElement = this._recorder.document.createElement(\"x-pw-dialog\");\n this._keyboardListener = (event) => {\n var _a;\n if (event.key === \"Escape\") {\n this.close();\n (_a = options.onCancel) == null ? void 0 : _a.call(options);\n return;\n }\n if (event.key === \"Enter\" && (event.ctrlKey || event.metaKey)) {\n if (this._dialogElement)\n options.onCommit();\n return;\n }\n };\n this._recorder.document.addEventListener(\"keydown\", this._keyboardListener, true);\n const toolbarElement = this._recorder.document.createElement(\"x-pw-tools-list\");\n const labelElement = this._recorder.document.createElement(\"label\");\n labelElement.textContent = options.label;\n toolbarElement.appendChild(labelElement);\n toolbarElement.appendChild(this._recorder.document.createElement(\"x-spacer\"));\n toolbarElement.appendChild(acceptButton);\n toolbarElement.appendChild(cancelButton);\n this._dialogElement.appendChild(toolbarElement);\n const bodyElement = this._recorder.document.createElement(\"x-pw-dialog-body\");\n bodyElement.appendChild(options.body);\n this._dialogElement.appendChild(bodyElement);\n this._recorder.highlight.appendChild(this._dialogElement);\n return this._dialogElement;\n }\n moveTo(top, left) {\n if (!this._dialogElement)\n return;\n this._dialogElement.style.top = top + \"px\";\n this._dialogElement.style.left = left + \"px\";\n }\n close() {\n if (!this._dialogElement)\n return;\n this._dialogElement.remove();\n this._recorder.document.removeEventListener(\"keydown\", this._keyboardListener);\n this._dialogElement = null;\n }\n};\nfunction deepActiveElement(document) {\n let activeElement = document.activeElement;\n while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)\n activeElement = activeElement.shadowRoot.activeElement;\n return activeElement;\n}\nfunction modifiersForEvent(event) {\n return (event.altKey ? 1 : 0) | (event.ctrlKey ? 2 : 0) | (event.metaKey ? 4 : 0) | (event.shiftKey ? 8 : 0);\n}\nfunction buttonForEvent(event) {\n switch (event.which) {\n case 1:\n return \"left\";\n case 2:\n return \"middle\";\n case 3:\n return \"right\";\n }\n return \"left\";\n}\nfunction positionForEvent(event) {\n const targetElement = event.target;\n if (targetElement.nodeName !== \"CANVAS\")\n return;\n return {\n x: event.offsetX,\n y: event.offsetY\n };\n}\nfunction consumeEvent(e) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n}\nfunction asCheckbox(node) {\n if (!node || node.nodeName !== \"INPUT\")\n return null;\n const inputElement = node;\n return [\"checkbox\", \"radio\"].includes(inputElement.type) ? inputElement : null;\n}\nfunction isRangeInput(node) {\n if (!node || node.nodeName !== \"INPUT\")\n return false;\n const inputElement = node;\n return inputElement.type.toLowerCase() === \"range\";\n}\nfunction addEventListener(target, eventName, listener, useCapture) {\n target.addEventListener(eventName, listener, useCapture);\n const remove = () => {\n target.removeEventListener(eventName, listener, useCapture);\n };\n return remove;\n}\nfunction removeEventListeners(listeners) {\n for (const listener of listeners)\n listener();\n listeners.splice(0, listeners.length);\n}\nfunction querySelector(injectedScript, selector, ownerDocument) {\n try {\n const parsedSelector = injectedScript.parseSelector(selector);\n return {\n selector,\n elements: injectedScript.querySelectorAll(parsedSelector, ownerDocument)\n };\n } catch (e) {\n return {\n selector,\n elements: []\n };\n }\n}\nfunction createSvgElement(doc, { tagName, attrs, children }) {\n const elem = doc.createElementNS(\"http://www.w3.org/2000/svg\", tagName);\n if (attrs) {\n for (const [k, v] of Object.entries(attrs))\n elem.setAttribute(k, v);\n }\n if (children) {\n for (const c of children)\n elem.appendChild(createSvgElement(doc, c));\n }\n return elem;\n}\n\n// packages/playwright-core/src/server/injected/recorder/pollingRecorder.ts\nvar PollingRecorder = class {\n constructor(injectedScript) {\n this._recorder = new Recorder(injectedScript);\n this._embedder = injectedScript.window;\n injectedScript.onGlobalListenersRemoved.add(() => this._recorder.installListeners());\n const refreshOverlay = () => {\n this._pollRecorderMode().catch((e) => console.log(e));\n };\n this._embedder.__pw_refreshOverlay = refreshOverlay;\n refreshOverlay();\n }\n async _pollRecorderMode() {\n const pollPeriod = 1e3;\n if (this._pollRecorderModeTimer)\n clearTimeout(this._pollRecorderModeTimer);\n const state = await this._embedder.__pw_recorderState().catch(() => {\n });\n if (!state) {\n this._pollRecorderModeTimer = this._recorder.injectedScript.builtinSetTimeout(() => this._pollRecorderMode(), pollPeriod);\n return;\n }\n const win = this._recorder.document.defaultView;\n if (win.top !== win) {\n state.actionPoint = void 0;\n }\n this._recorder.setUIState(state, this);\n this._pollRecorderModeTimer = this._recorder.injectedScript.builtinSetTimeout(() => this._pollRecorderMode(), pollPeriod);\n }\n async performAction(action) {\n await this._embedder.__pw_recorderPerformAction(action);\n }\n async recordAction(action) {\n await this._embedder.__pw_recorderRecordAction(action);\n }\n async elementPicked(elementInfo) {\n await this._embedder.__pw_recorderElementPicked(elementInfo);\n }\n async setMode(mode) {\n await this._embedder.__pw_recorderSetMode(mode);\n }\n async setOverlayState(state) {\n await this._embedder.__pw_recorderSetOverlayState(state);\n }\n};\nvar pollingRecorder_default = PollingRecorder;\n";
const source = exports.source = "\nvar __commonJS = obj => {\n let required = false;\n let result;\n return function __require() {\n if (!required) {\n required = true;\n let fn;\n for (const name in obj) { fn = obj[name]; break; }\n const module = { exports: {} };\n fn(module.exports, module);\n result = module.exports;\n }\n return result;\n }\n};\nvar __export = (target, all) => {for (var name in all) target[name] = all[name];};\nvar __toESM = mod => ({ ...mod, 'default': mod });\nvar __toCommonJS = mod => ({ ...mod, __esModule: true });\n\n\n// packages/playwright-core/src/server/injected/recorder/pollingRecorder.ts\nvar pollingRecorder_exports = {};\n__export(pollingRecorder_exports, {\n PollingRecorder: () => PollingRecorder,\n default: () => pollingRecorder_default\n});\nmodule.exports = __toCommonJS(pollingRecorder_exports);\n\n// packages/playwright-core/src/server/injected/recorder/clipPaths.ts\nvar svgJson = { \"tagName\": \"svg\", \"children\": [{ \"tagName\": \"defs\", \"children\": [{ \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-gripper\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"d\": \"M5 3h2v2H5zm0 4h2v2H5zm0 4h2v2H5zm4-8h2v2H9zm0 4h2v2H9zm0 4h2v2H9z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-circle-large-filled\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"d\": \"M8 1a6.8 6.8 0 0 1 1.86.253 6.899 6.899 0 0 1 3.083 1.805 6.903 6.903 0 0 1 1.804 3.083C14.916 6.738 15 7.357 15 8s-.084 1.262-.253 1.86a6.9 6.9 0 0 1-.704 1.674 7.157 7.157 0 0 1-2.516 2.509 6.966 6.966 0 0 1-1.668.71A6.984 6.984 0 0 1 8 15a6.984 6.984 0 0 1-1.86-.246 7.098 7.098 0 0 1-1.674-.711 7.3 7.3 0 0 1-1.415-1.094 7.295 7.295 0 0 1-1.094-1.415 7.098 7.098 0 0 1-.71-1.675A6.985 6.985 0 0 1 1 8c0-.643.082-1.262.246-1.86a6.968 6.968 0 0 1 .711-1.667 7.156 7.156 0 0 1 2.509-2.516 6.895 6.895 0 0 1 1.675-.704A6.808 6.808 0 0 1 8 1z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-inspect\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M1 3l1-1h12l1 1v6h-1V3H2v8h5v1H2l-1-1V3zm14.707 9.707L9 6v9.414l2.707-2.707h4zM10 13V8.414l3.293 3.293h-2L10 13z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-whole-word\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M0 11H1V13H15V11H16V14H15H1H0V11Z\" } }, { \"tagName\": \"path\", \"attrs\": { \"d\": \"M6.84048 11H5.95963V10.1406H5.93814C5.555 10.7995 4.99104 11.1289 4.24625 11.1289C3.69839 11.1289 3.26871 10.9839 2.95718 10.6938C2.64924 10.4038 2.49527 10.0189 2.49527 9.53906C2.49527 8.51139 3.10041 7.91341 4.3107 7.74512L5.95963 7.51416C5.95963 6.57959 5.58186 6.1123 4.82632 6.1123C4.16389 6.1123 3.56591 6.33789 3.03238 6.78906V5.88672C3.57307 5.54297 4.19612 5.37109 4.90152 5.37109C6.19416 5.37109 6.84048 6.05501 6.84048 7.42285V11ZM5.95963 8.21777L4.63297 8.40039C4.22476 8.45768 3.91682 8.55973 3.70914 8.70654C3.50145 8.84977 3.39761 9.10579 3.39761 9.47461C3.39761 9.74316 3.4925 9.96338 3.68228 10.1353C3.87564 10.3035 4.13166 10.3877 4.45035 10.3877C4.8872 10.3877 5.24706 10.2355 5.52994 9.93115C5.8164 9.62321 5.95963 9.2347 5.95963 8.76562V8.21777Z\" } }, { \"tagName\": \"path\", \"attrs\": { \"d\": \"M9.3475 10.2051H9.32601V11H8.44515V2.85742H9.32601V6.4668H9.3475C9.78076 5.73633 10.4146 5.37109 11.2489 5.37109C11.9543 5.37109 12.5057 5.61816 12.9032 6.1123C13.3042 6.60286 13.5047 7.26172 13.5047 8.08887C13.5047 9.00911 13.2809 9.74674 12.8333 10.3018C12.3857 10.8532 11.7734 11.1289 10.9964 11.1289C10.2695 11.1289 9.71989 10.821 9.3475 10.2051ZM9.32601 7.98682V8.75488C9.32601 9.20964 9.47282 9.59635 9.76644 9.91504C10.0636 10.2301 10.4396 10.3877 10.8944 10.3877C11.4279 10.3877 11.8451 10.1836 12.1458 9.77539C12.4502 9.36719 12.6024 8.79964 12.6024 8.07275C12.6024 7.46045 12.4609 6.98063 12.1781 6.6333C11.8952 6.28597 11.512 6.1123 11.0286 6.1123C10.5166 6.1123 10.1048 6.29134 9.7933 6.64941C9.48177 7.00391 9.32601 7.44971 9.32601 7.98682Z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-eye\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"d\": \"M7.99993 6.00316C9.47266 6.00316 10.6666 7.19708 10.6666 8.66981C10.6666 10.1426 9.47266 11.3365 7.99993 11.3365C6.52715 11.3365 5.33324 10.1426 5.33324 8.66981C5.33324 7.19708 6.52715 6.00316 7.99993 6.00316ZM7.99993 7.00315C7.07946 7.00315 6.33324 7.74935 6.33324 8.66981C6.33324 9.59028 7.07946 10.3365 7.99993 10.3365C8.9204 10.3365 9.6666 9.59028 9.6666 8.66981C9.6666 7.74935 8.9204 7.00315 7.99993 7.00315ZM7.99993 3.66675C11.0756 3.66675 13.7307 5.76675 14.4673 8.70968C14.5344 8.97755 14.3716 9.24908 14.1037 9.31615C13.8358 9.38315 13.5643 9.22041 13.4973 8.95248C12.8713 6.45205 10.6141 4.66675 7.99993 4.66675C5.38454 4.66675 3.12664 6.45359 2.50182 8.95555C2.43491 9.22341 2.16348 9.38635 1.89557 9.31948C1.62766 9.25255 1.46471 8.98115 1.53162 8.71321C2.26701 5.76856 4.9229 3.66675 7.99993 3.66675Z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-symbol-constant\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M4 6h8v1H4V6zm8 3H4v1h8V9z\" } }, { \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M1 4l1-1h12l1 1v8l-1 1H2l-1-1V4zm1 0v8h12V4H2z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-check\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M14.431 3.323l-8.47 10-.79-.036-3.35-4.77.818-.574 2.978 4.24 8.051-9.506.764.646z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-close\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M8 8.707l3.646 3.647.708-.707L8.707 8l3.647-3.646-.707-.708L8 7.293 4.354 3.646l-.707.708L7.293 8l-3.646 3.646.707.708L8 8.707z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-pass\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"d\": \"M6.27 10.87h.71l4.56-4.56-.71-.71-4.2 4.21-1.92-1.92L4 8.6l2.27 2.27z\" } }, { \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M8.6 1c1.6.1 3.1.9 4.2 2 1.3 1.4 2 3.1 2 5.1 0 1.6-.6 3.1-1.6 4.4-1 1.2-2.4 2.1-4 2.4-1.6.3-3.2.1-4.6-.7-1.4-.8-2.5-2-3.1-3.5C.9 9.2.8 7.5 1.3 6c.5-1.6 1.4-2.9 2.8-3.8C5.4 1.3 7 .9 8.6 1zm.5 12.9c1.3-.3 2.5-1 3.4-2.1.8-1.1 1.3-2.4 1.2-3.8 0-1.6-.6-3.2-1.7-4.3-1-1-2.2-1.6-3.6-1.7-1.3-.1-2.7.2-3.8 1-1.1.8-1.9 1.9-2.3 3.3-.4 1.3-.4 2.7.2 4 .6 1.3 1.5 2.3 2.7 3 1.2.7 2.6.9 3.9.6z\" } }] }, { \"tagName\": \"clipPath\", \"attrs\": { \"width\": \"16\", \"height\": \"16\", \"viewBox\": \"0 0 16 16\", \"fill\": \"currentColor\", \"id\": \"icon-gist\" }, \"children\": [{ \"tagName\": \"path\", \"attrs\": { \"fill-rule\": \"evenodd\", \"clip-rule\": \"evenodd\", \"d\": \"M10.57 1.14l3.28 3.3.15.36v9.7l-.5.5h-11l-.5-.5v-13l.5-.5h7.72l.35.14zM10 5h3l-3-3v3zM3 2v12h10V6H9.5L9 5.5V2H3zm2.062 7.533l1.817-1.828L6.17 7 4 9.179v.707l2.171 2.174.707-.707-1.816-1.82zM8.8 7.714l.7-.709 2.189 2.175v.709L9.5 12.062l-.705-.709 1.831-1.82L8.8 7.714z\" } }] }] }] };\nvar clipPaths_default = svgJson;\n\n// packages/playwright-core/src/server/injected/recorder/recorder.ts\nvar NoneTool = class {\n cursor() {\n return \"default\";\n }\n};\nvar InspectTool = class {\n constructor(recorder, assertVisibility) {\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._hoveredSelectors = null;\n this._recorder = recorder;\n this._assertVisibility = assertVisibility;\n }\n cursor() {\n return \"pointer\";\n }\n cleanup() {\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._hoveredSelectors = null;\n }\n onClick(event) {\n var _a;\n consumeEvent(event);\n if (event.button !== 0)\n return;\n if ((_a = this._hoveredModel) == null ? void 0 : _a.selector)\n this._commit(this._hoveredModel.selector, this._hoveredModel);\n }\n onContextMenu(event) {\n if (this._hoveredModel && !this._hoveredModel.tooltipListItemSelected && this._hoveredSelectors && this._hoveredSelectors.length > 1) {\n consumeEvent(event);\n const selectors = this._hoveredSelectors;\n const hoveredModel = this._hoveredModel;\n this._hoveredModel.tooltipFooter = void 0;\n this._hoveredModel.tooltipList = selectors.map((selector) => this._recorder.injectedScript.utils.asLocator(this._recorder.state.language, selector));\n this._hoveredModel.tooltipListItemSelected = (index) => {\n if (index === void 0)\n this._reset(true);\n else\n this._commit(selectors[index], hoveredModel);\n };\n this._recorder.updateHighlight(this._hoveredModel, true);\n }\n }\n onPointerDown(event) {\n consumeEvent(event);\n }\n onPointerUp(event) {\n consumeEvent(event);\n }\n onMouseDown(event) {\n consumeEvent(event);\n }\n onMouseUp(event) {\n consumeEvent(event);\n }\n onMouseMove(event) {\n var _a;\n consumeEvent(event);\n let target = this._recorder.deepEventTarget(event);\n if (!target.isConnected)\n target = null;\n if (this._hoveredElement === target)\n return;\n this._hoveredElement = target;\n let model = null;\n let selectors = [];\n if (this._hoveredElement) {\n const generated = this._recorder.injectedScript.generateSelector(this._hoveredElement, { testIdAttributeName: this._recorder.state.testIdAttributeName, multiple: false });\n selectors = generated.selectors;\n model = {\n selector: generated.selector,\n elements: generated.elements,\n tooltipText: this._recorder.injectedScript.utils.asLocator(this._recorder.state.language, generated.selector),\n tooltipFooter: selectors.length > 1 ? `Click to select, right-click for more options` : void 0,\n color: this._assertVisibility ? \"#8acae480\" : void 0\n };\n }\n if (((_a = this._hoveredModel) == null ? void 0 : _a.selector) === (model == null ? void 0 : model.selector))\n return;\n this._hoveredModel = model;\n this._hoveredSelectors = selectors;\n this._recorder.updateHighlight(model, true);\n }\n onMouseEnter(event) {\n consumeEvent(event);\n }\n onMouseLeave(event) {\n consumeEvent(event);\n const window = this._recorder.injectedScript.window;\n if (window.top !== window && this._recorder.deepEventTarget(event).nodeType === Node.DOCUMENT_NODE)\n this._reset(true);\n }\n onKeyDown(event) {\n var _a;\n consumeEvent(event);\n if (event.key === \"Escape\") {\n if ((_a = this._hoveredModel) == null ? void 0 : _a.tooltipListItemSelected)\n this._reset(true);\n else if (this._assertVisibility)\n this._recorder.setMode(\"recording\");\n }\n }\n onKeyUp(event) {\n consumeEvent(event);\n }\n onScroll(event) {\n this._reset(false);\n }\n _commit(selector, model) {\n var _a;\n if (this._assertVisibility) {\n this._recorder.recordAction({\n name: \"assertVisible\",\n selector,\n signals: []\n });\n this._recorder.setMode(\"recording\");\n (_a = this._recorder.overlay) == null ? void 0 : _a.flashToolSucceeded(\"assertingVisibility\");\n } else {\n this._recorder.elementPicked(selector, model);\n }\n }\n _reset(userGesture) {\n this._hoveredElement = null;\n this._hoveredModel = null;\n this._hoveredSelectors = null;\n this._recorder.updateHighlight(null, userGesture);\n }\n};\nvar RecordActionTool = class {\n constructor(recorder) {\n this._performingActions = /* @__PURE__ */ new Set();\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._activeModel = null;\n this._expectProgrammaticKeyUp = false;\n this._recorder = recorder;\n }\n cursor() {\n return \"pointer\";\n }\n cleanup() {\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._activeModel = null;\n this._expectProgrammaticKeyUp = false;\n }\n onClick(event) {\n if (isRangeInput(this._hoveredElement))\n return;\n if (event.button === 2 && event.type === \"auxclick\")\n return;\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (this._actionInProgress(event))\n return;\n if (this._consumedDueToNoModel(event, this._hoveredModel))\n return;\n const checkbox = asCheckbox(this._recorder.deepEventTarget(event));\n if (checkbox) {\n this._performAction({\n name: checkbox.checked ? \"check\" : \"uncheck\",\n selector: this._hoveredModel.selector,\n signals: []\n });\n return;\n }\n this._cancelPendingClickAction();\n if (event.detail === 1) {\n this._pendingClickAction = {\n action: {\n name: \"click\",\n selector: this._hoveredModel.selector,\n position: positionForEvent(event),\n signals: [],\n button: buttonForEvent(event),\n modifiers: modifiersForEvent(event),\n clickCount: event.detail\n },\n timeout: this._recorder.injectedScript.builtinSetTimeout(() => this._commitPendingClickAction(), 200)\n };\n }\n }\n onDblClick(event) {\n if (isRangeInput(this._hoveredElement))\n return;\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (this._actionInProgress(event))\n return;\n if (this._consumedDueToNoModel(event, this._hoveredModel))\n return;\n this._cancelPendingClickAction();\n this._performAction({\n name: \"click\",\n selector: this._hoveredModel.selector,\n position: positionForEvent(event),\n signals: [],\n button: buttonForEvent(event),\n modifiers: modifiersForEvent(event),\n clickCount: event.detail\n });\n }\n _commitPendingClickAction() {\n if (this._pendingClickAction)\n this._performAction(this._pendingClickAction.action);\n this._cancelPendingClickAction();\n }\n _cancelPendingClickAction() {\n if (this._pendingClickAction)\n clearTimeout(this._pendingClickAction.timeout);\n this._pendingClickAction = void 0;\n }\n onContextMenu(event) {\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (this._actionInProgress(event))\n return;\n if (this._consumedDueToNoModel(event, this._hoveredModel))\n return;\n this._performAction({\n name: \"click\",\n selector: this._hoveredModel.selector,\n position: positionForEvent(event),\n signals: [],\n button: \"right\",\n modifiers: 0,\n clickCount: 0\n });\n }\n onPointerDown(event) {\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (!this._performingActions.size)\n consumeEvent(event);\n }\n onPointerUp(event) {\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (!this._performingActions.size)\n consumeEvent(event);\n }\n onMouseDown(event) {\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (!this._performingActions.size)\n consumeEvent(event);\n this._activeModel = this._hoveredModel;\n }\n onMouseUp(event) {\n if (this._shouldIgnoreMouseEvent(event))\n return;\n if (!this._performingActions.size)\n consumeEvent(event);\n }\n onMouseMove(event) {\n const target = this._recorder.deepEventTarget(event);\n if (this._hoveredElement === target)\n return;\n this._hoveredElement = target;\n this._updateModelForHoveredElement();\n }\n onMouseLeave(event) {\n const window = this._recorder.injectedScript.window;\n if (window.top !== window && this._recorder.deepEventTarget(event).nodeType === Node.DOCUMENT_NODE) {\n this._hoveredElement = null;\n this._updateModelForHoveredElement();\n }\n }\n onFocus(event) {\n this._onFocus(true);\n }\n onInput(event) {\n const target = this._recorder.deepEventTarget(event);\n if (target.nodeName === \"INPUT\" && target.type.toLowerCase() === \"file\") {\n this._recorder.recordAction({\n name: \"setInputFiles\",\n selector: this._activeModel.selector,\n signals: [],\n files: [...target.files || []].map((file) => file.name)\n });\n return;\n }\n if (isRangeInput(target)) {\n this._recorder.recordAction({\n name: \"fill\",\n // must use hoveredModel instead of activeModel for it to work in webkit\n selector: this._hoveredModel.selector,\n signals: [],\n text: target.value\n });\n return;\n }\n if ([\"INPUT\", \"TEXTAREA\"].includes(target.nodeName) || target.isContentEditable) {\n if (target.nodeName === \"INPUT\" && [\"checkbox\", \"radio\"].includes(target.type.toLowerCase())) {\n return;\n }\n if (this._consumedDueWrongTarget(event))\n return;\n this._recorder.recordAction({\n name: \"fill\",\n selector: this._activeModel.selector,\n signals: [],\n text: target.isContentEditable ? target.innerText : target.value\n });\n }\n if (target.nodeName === \"SELECT\") {\n const selectElement = target;\n if (this._actionInProgress(event))\n return;\n this._performAction({\n name: \"select\",\n selector: this._activeModel.selector,\n options: [...selectElement.selectedOptions].map((option) => option.value),\n signals: []\n });\n }\n }\n onKeyDown(event) {\n if (!this._shouldGenerateKeyPressFor(event))\n return;\n if (this._actionInProgress(event)) {\n this._expectProgrammaticKeyUp = true;\n return;\n }\n if (this._consumedDueWrongTarget(event))\n return;\n if (event.key === \" \") {\n const checkbox = asCheckbox(this._recorder.deepEventTarget(event));\n if (checkbox) {\n this._performAction({\n name: checkbox.checked ? \"uncheck\" : \"check\",\n selector: this._activeModel.selector,\n signals: []\n });\n return;\n }\n }\n this._performAction({\n name: \"press\",\n selector: this._activeModel.selector,\n signals: [],\n key: event.key,\n modifiers: modifiersForEvent(event)\n });\n }\n onKeyUp(event) {\n if (!this._shouldGenerateKeyPressFor(event))\n return;\n if (!this._expectProgrammaticKeyUp) {\n consumeEvent(event);\n return;\n }\n this._expectProgrammaticKeyUp = false;\n }\n onScroll(event) {\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._recorder.updateHighlight(null, false);\n }\n _onFocus(userGesture) {\n const activeElement = deepActiveElement(this._recorder.document);\n if (userGesture && activeElement === this._recorder.document.body)\n return;\n const result = activeElement ? this._recorder.injectedScript.generateSelector(activeElement, { testIdAttributeName: this._recorder.state.testIdAttributeName }) : null;\n this._activeModel = result && result.selector ? result : null;\n if (userGesture) {\n this._hoveredElement = activeElement;\n this._updateModelForHoveredElement();\n }\n }\n _shouldIgnoreMouseEvent(event) {\n const target = this._recorder.deepEventTarget(event);\n const nodeName = target.nodeName;\n if (nodeName === \"SELECT\" || nodeName === \"OPTION\")\n return true;\n if (nodeName === \"INPUT\" && [\"date\", \"range\"].includes(target.type))\n return true;\n return false;\n }\n _actionInProgress(event) {\n const isKeyEvent = event instanceof KeyboardEvent;\n const isMouseOrPointerEvent = event instanceof MouseEvent || event instanceof PointerEvent;\n for (const action of this._performingActions) {\n if (isKeyEvent && action.name === \"press\" && event.key === action.key)\n return true;\n if (isMouseOrPointerEvent && (action.name === \"click\" || action.name === \"check\" || action.name === \"uncheck\"))\n return true;\n }\n consumeEvent(event);\n return false;\n }\n _consumedDueToNoModel(event, model) {\n if (model)\n return false;\n consumeEvent(event);\n return true;\n }\n _consumedDueWrongTarget(event) {\n if (this._activeModel && this._activeModel.elements[0] === this._recorder.deepEventTarget(event))\n return false;\n consumeEvent(event);\n return true;\n }\n _performAction(action) {\n this._hoveredElement = null;\n this._hoveredModel = null;\n this._activeModel = null;\n this._recorder.updateHighlight(null, false);\n this._performingActions.add(action);\n void this._recorder.performAction(action).then(() => {\n this._performingActions.delete(action);\n this._onFocus(false);\n if (this._recorder.injectedScript.isUnderTest) {\n console.error(\"Action performed for test: \" + JSON.stringify({\n // eslint-disable-line no-console\n hovered: this._hoveredModel ? this._hoveredModel.selector : null,\n active: this._activeModel ? this._activeModel.selector : null\n }));\n }\n });\n }\n _shouldGenerateKeyPressFor(event) {\n if (event.key === \"Enter\" && (this._recorder.deepEventTarget(event).nodeName === \"TEXTAREA\" || this._recorder.deepEventTarget(event).isContentEditable))\n return false;\n if ([\"Backspace\", \"Delete\", \"AltGraph\"].includes(event.key))\n return false;\n if (event.key === \"@\" && event.code === \"KeyL\")\n return false;\n if (navigator.platform.includes(\"Mac\")) {\n if (event.key === \"v\" && event.metaKey)\n return false;\n } else {\n if (event.key === \"v\" && event.ctrlKey)\n return false;\n if (event.key === \"Insert\" && event.shiftKey)\n return false;\n }\n if ([\"Shift\", \"Control\", \"Meta\", \"Alt\", \"Process\"].includes(event.key))\n return false;\n const hasModifier = event.ctrlKey || event.altKey || event.metaKey;\n if (event.key.length === 1 && !hasModifier)\n return !!asCheckbox(this._recorder.deepEventTarget(event));\n return true;\n }\n _updateModelForHoveredElement() {\n if (this._performingActions.size)\n return;\n if (!this._hoveredElement || !this._hoveredElement.isConnected) {\n this._hoveredModel = null;\n this._hoveredElement = null;\n this._recorder.updateHighlight(null, true);\n return;\n }\n const { selector, elements } = this._recorder.injectedScript.generateSelector(this._hoveredElement, { testIdAttributeName: this._recorder.state.testIdAttributeName });\n if (this._hoveredModel && this._hoveredModel.selector === selector)\n return;\n this._hoveredModel = selector ? { selector, elements, color: \"#dc6f6f7f\" } : null;\n this._recorder.updateHighlight(this._hoveredModel, true);\n }\n};\nvar TextAssertionTool = class {\n constructor(recorder, kind) {\n this._hoverHighlight = null;\n this._action = null;\n this._textCache = /* @__PURE__ */ new Map();\n this._recorder = recorder;\n this._kind = kind;\n this._dialog = new Dialog(recorder);\n }\n cursor() {\n return \"pointer\";\n }\n cleanup() {\n this._dialog.close();\n this._hoverHighlight = null;\n }\n onClick(event) {\n consumeEvent(event);\n if (this._kind === \"value\") {\n this._commitAssertValue();\n } else {\n if (!this._dialog.isShowing())\n this._showDialog();\n }\n }\n onMouseDown(event) {\n const target = this._recorder.deepEventTarget(event);\n if (this._elementHasValue(target))\n event.preventDefault();\n }\n onPointerUp(event) {\n var _a;\n const target = (_a = this._hoverHighlight) == null ? void 0 : _a.elements[0];\n if (this._kind === \"value\" && target && (target.nodeName === \"INPUT\" || target.nodeName === \"SELECT\") && target.disabled) {\n this._commitAssertValue();\n }\n }\n onMouseMove(event) {\n var _a;\n if (this._dialog.isShowing())\n return;\n const target = this._recorder.deepEventTarget(event);\n if (((_a = this._hoverHighlight) == null ? void 0 : _a.elements[0]) === target)\n return;\n if (this._kind === \"text\" || this._kind === \"snapshot\")\n this._hoverHighlight = this._recorder.injectedScript.utils.elementText(this._textCache, target).full ? { elements: [target], selector: \"\" } : null;\n else\n this._hoverHighlight = this._elementHasValue(target) ? this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName }) : null;\n if (this._hoverHighlight)\n this._hoverHighlight.color = \"#8acae480\";\n this._recorder.updateHighlight(this._hoverHighlight, true);\n }\n onKeyDown(event) {\n if (event.key === \"Escape\")\n this._recorder.setMode(\"recording\");\n consumeEvent(event);\n }\n onScroll(event) {\n this._recorder.updateHighlight(this._hoverHighlight, false);\n }\n _elementHasValue(element) {\n return element.nodeName === \"TEXTAREA\" || element.nodeName === \"SELECT\" || element.nodeName === \"INPUT\" && ![\"button\", \"image\", \"reset\", \"submit\"].includes(element.type);\n }\n _generateAction() {\n var _a;\n this._textCache.clear();\n const target = (_a = this._hoverHighlight) == null ? void 0 : _a.elements[0];\n if (!target)\n return null;\n if (this._kind === \"value\") {\n if (!this._elementHasValue(target))\n return null;\n const { selector } = this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName });\n if (target.nodeName === \"INPUT\" && [\"checkbox\", \"radio\"].includes(target.type.toLowerCase())) {\n return {\n name: \"assertChecked\",\n selector,\n signals: [],\n // Interestingly, inputElement.checked is reversed inside this event handler.\n checked: !target.checked\n };\n } else {\n return {\n name: \"assertValue\",\n selector,\n signals: [],\n value: target.value\n };\n }\n } else if (this._kind === \"snapshot\") {\n this._hoverHighlight = this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName, forTextExpect: true });\n this._hoverHighlight.color = \"#8acae480\";\n this._recorder.updateHighlight(this._hoverHighlight, true);\n return {\n name: \"assertSnapshot\",\n selector: this._hoverHighlight.selector,\n signals: [],\n snapshot: this._recorder.injectedScript.ariaSnapshot(target, { mode: \"regex\" })\n };\n } else {\n this._hoverHighlight = this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName, forTextExpect: true });\n this._hoverHighlight.color = \"#8acae480\";\n this._recorder.updateHighlight(this._hoverHighlight, true);\n return {\n name: \"assertText\",\n selector: this._hoverHighlight.selector,\n signals: [],\n text: this._recorder.injectedScript.utils.elementText(this._textCache, target).normalized,\n substring: true\n };\n }\n }\n _renderValue(action) {\n if ((action == null ? void 0 : action.name) === \"assertText\")\n return this._recorder.injectedScript.utils.normalizeWhiteSpace(action.text);\n if ((action == null ? void 0 : action.name) === \"assertChecked\")\n return String(action.checked);\n if ((action == null ? void 0 : action.name) === \"assertValue\")\n return action.value;\n if ((action == null ? void 0 : action.name) === \"assertSnapshot\")\n return action.snapshot;\n return \"\";\n }\n _commit() {\n if (!this._action || !this._dialog.isShowing())\n return;\n this._dialog.close();\n this._recorder.recordAction(this._action);\n this._recorder.setMode(\"recording\");\n }\n _showDialog() {\n var _a, _b, _c, _d;\n if (!((_a = this._hoverHighlight) == null ? void 0 : _a.elements[0]))\n return;\n this._action = this._generateAction();\n if (((_b = this._action) == null ? void 0 : _b.name) === \"assertText\") {\n this._showTextDialog(this._action);\n } else if (((_c = this._action) == null ? void 0 : _c.name) === \"assertSnapshot\") {\n this._recorder.recordAction(this._action);\n this._recorder.setMode(\"recording\");\n (_d = this._recorder.overlay) == null ? void 0 : _d.flashToolSucceeded(\"assertingSnapshot\");\n }\n }\n _showTextDialog(action) {\n const textElement = this._recorder.document.createElement(\"textarea\");\n textElement.setAttribute(\"spellcheck\", \"false\");\n textElement.value = this._renderValue(action);\n textElement.classList.add(\"text-editor\");\n const updateAndValidate = () => {\n var _a;\n const newValue = this._recorder.injectedScript.utils.normalizeWhiteSpace(textElement.value);\n const target = (_a = this._hoverHighlight) == null ? void 0 : _a.elements[0];\n if (!target)\n return;\n action.text = newValue;\n const targetText = this._recorder.injectedScript.utils.elementText(this._textCache, target).normalized;\n const matches = newValue && targetText.includes(newValue);\n textElement.classList.toggle(\"does-not-match\", !matches);\n };\n textElement.addEventListener(\"input\", updateAndValidate);\n const label = \"Assert that element contains text\";\n const dialogElement = this._dialog.show({\n label,\n body: textElement,\n onCommit: () => this._commit()\n });\n const position = this._recorder.highlight.tooltipPosition(this._recorder.highlight.firstBox(), dialogElement);\n this._dialog.moveTo(position.anchorTop, position.anchorLeft);\n textElement.focus();\n }\n _commitAssertValue() {\n var _a;\n if (this._kind !== \"value\")\n return;\n const action = this._generateAction();\n if (!action)\n return;\n this._recorder.recordAction(action);\n this._recorder.setMode(\"recording\");\n (_a = this._recorder.overlay) == null ? void 0 : _a.flashToolSucceeded(\"assertingValue\");\n }\n};\nvar Overlay = class {\n constructor(recorder) {\n this._listeners = [];\n this._offsetX = 0;\n this._measure = { width: 0, height: 0 };\n this._recorder = recorder;\n const document = this._recorder.document;\n this._overlayElement = document.createElement(\"x-pw-overlay\");\n const toolsListElement = document.createElement(\"x-pw-tools-list\");\n this._overlayElement.appendChild(toolsListElement);\n this._dragHandle = document.createElement(\"x-pw-tool-gripper\");\n this._dragHandle.appendChild(document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._dragHandle);\n this._recordToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._recordToggle.title = \"Record\";\n this._recordToggle.classList.add(\"record\");\n this._recordToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._recordToggle);\n this._pickLocatorToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._pickLocatorToggle.title = \"Pick locator\";\n this._pickLocatorToggle.classList.add(\"pick-locator\");\n this._pickLocatorToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._pickLocatorToggle);\n this._assertVisibilityToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._assertVisibilityToggle.title = \"Assert visibility\";\n this._assertVisibilityToggle.classList.add(\"visibility\");\n this._assertVisibilityToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._assertVisibilityToggle);\n this._assertTextToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._assertTextToggle.title = \"Assert text\";\n this._assertTextToggle.classList.add(\"text\");\n this._assertTextToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._assertTextToggle);\n this._assertValuesToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._assertValuesToggle.title = \"Assert value\";\n this._assertValuesToggle.classList.add(\"value\");\n this._assertValuesToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._assertValuesToggle);\n this._assertSnapshotToggle = this._recorder.document.createElement(\"x-pw-tool-item\");\n this._assertSnapshotToggle.title = \"Assert snapshot\";\n this._assertSnapshotToggle.classList.add(\"snapshot\");\n this._assertSnapshotToggle.appendChild(this._recorder.document.createElement(\"x-div\"));\n toolsListElement.appendChild(this._assertSnapshotToggle);\n this._updateVisualPosition();\n this._refreshListeners();\n }\n _refreshListeners() {\n removeEventListeners(this._listeners);\n this._listeners = [\n addEventListener(this._dragHandle, \"mousedown\", (event) => {\n this._dragState = { offsetX: this._offsetX, dragStart: { x: event.clientX, y: 0 } };\n }),\n addEventListener(this._recordToggle, \"click\", () => {\n if (this._recordToggle.classList.contains(\"disabled\"))\n return;\n this._recorder.setMode(this._recorder.state.mode === \"none\" || this._recorder.state.mode === \"standby\" || this._recorder.state.mode === \"inspecting\" ? \"recording\" : \"standby\");\n }),\n addEventListener(this._pickLocatorToggle, \"click\", () => {\n if (this._pickLocatorToggle.classList.contains(\"disabled\"))\n return;\n const newMode = {\n \"inspecting\": \"standby\",\n \"none\": \"inspecting\",\n \"standby\": \"inspecting\",\n \"recording\": \"recording-inspecting\",\n \"recording-inspecting\": \"recording\",\n \"assertingText\": \"recording-inspecting\",\n \"assertingVisibility\": \"recording-inspecting\",\n \"assertingValue\": \"recording-inspecting\",\n \"assertingSnapshot\": \"recording-inspecting\"\n };\n this._recorder.setMode(newMode[this._recorder.state.mode]);\n }),\n addEventListener(this._assertVisibilityToggle, \"click\", () => {\n if (!this._assertVisibilityToggle.classList.contains(\"disabled\"))\n this._recorder.setMode(this._recorder.state.mode === \"assertingVisibility\" ? \"recording\" : \"assertingVisibility\");\n }),\n addEventListener(this._assertTextToggle, \"click\", () => {\n if (!this._assertTextToggle.classList.contains(\"disabled\"))\n this._recorder.setMode(this._recorder.state.mode === \"assertingText\" ? \"recording\" : \"assertingText\");\n }),\n addEventListener(this._assertValuesToggle, \"click\", () => {\n if (!this._assertValuesToggle.classList.contains(\"disabled\"))\n this._recorder.setMode(this._recorder.state.mode === \"assertingValue\" ? \"recording\" : \"assertingValue\");\n }),\n addEventListener(this._assertSnapshotToggle, \"click\", () => {\n if (!this._assertSnapshotToggle.classList.contains(\"disabled\"))\n this._recorder.setMode(this._recorder.state.mode === \"assertingSnapshot\" ? \"recording\" : \"assertingSnapshot\");\n })\n ];\n }\n install() {\n this._recorder.highlight.appendChild(this._overlayElement);\n this._refreshListeners();\n this._updateVisualPosition();\n }\n contains(element) {\n return this._recorder.injectedScript.utils.isInsideScope(this._overlayElement, element);\n }\n setUIState(state) {\n this._recordToggle.classList.toggle(\"toggled\", state.mode === \"recording\" || state.mode === \"assertingText\" || state.mode === \"assertingVisibility\" || state.mode === \"assertingValue\" || state.mode === \"assertingSnapshot\" || state.mode === \"recording-inspecting\");\n this._pickLocatorToggle.classList.toggle(\"toggled\", state.mode === \"inspecting\" || state.mode === \"recording-inspecting\");\n this._assertVisibilityToggle.classList.toggle(\"toggled\", state.mode === \"assertingVisibility\");\n this._assertVisibilityToggle.classList.toggle(\"disabled\", state.mode === \"none\" || state.mode === \"standby\" || state.mode === \"inspecting\");\n this._assertTextToggle.classList.toggle(\"toggled\", state.mode === \"assertingText\");\n this._assertTextToggle.classList.toggle(\"disabled\", state.mode === \"none\" || state.mode === \"standby\" || state.mode === \"inspecting\");\n this._assertValuesToggle.classList.toggle(\"toggled\", state.mode === \"assertingValue\");\n this._assertValuesToggle.classList.toggle(\"disabled\", state.mode === \"none\" || state.mode === \"standby\" || state.mode === \"inspecting\");\n this._assertSnapshotToggle.classList.toggle(\"toggled\", state.mode === \"assertingSnapshot\");\n this._assertSnapshotToggle.classList.toggle(\"disabled\", state.mode === \"none\" || state.mode === \"standby\" || state.mode === \"inspecting\");\n if (this._offsetX !== state.overlay.offsetX) {\n this._offsetX = state.overlay.offsetX;\n this._updateVisualPosition();\n }\n if (state.mode === \"none\")\n this._hideOverlay();\n else\n this._showOverlay();\n }\n flashToolSucceeded(tool) {\n let element;\n if (tool === \"assertingVisibility\")\n element = this._assertVisibilityToggle;\n else if (tool === \"assertingSnapshot\")\n element = this._assertSnapshotToggle;\n else\n element = this._assertValuesToggle;\n element.classList.add(\"succeeded\");\n this._recorder.injectedScript.builtinSetTimeout(() => element.classList.remove(\"succeeded\"), 2e3);\n }\n _hideOverlay() {\n this._overlayElement.setAttribute(\"hidden\", \"true\");\n }\n _showOverlay() {\n if (!this._overlayElement.hasAttribute(\"hidden\"))\n return;\n this._overlayElement.removeAttribute(\"hidden\");\n this._updateVisualPosition();\n }\n _updateVisualPosition() {\n this._measure = this._overlayElement.getBoundingClientRect();\n this._overlayElement.style.left = (this._recorder.injectedScript.window.innerWidth - this._measure.width) / 2 + this._offsetX + \"px\";\n }\n onMouseMove(event) {\n if (!event.buttons) {\n this._dragState = void 0;\n return false;\n }\n if (this._dragState) {\n this._offsetX = this._dragState.offsetX + event.clientX - this._dragState.dragStart.x;\n const halfGapSize = (this._recorder.injectedScript.window.innerWidth - this._measure.width) / 2 - 10;\n this._offsetX = Math.max(-halfGapSize, Math.min(halfGapSize, this._offsetX));\n this._updateVisualPosition();\n this._recorder.setOverlayState({ offsetX: this._offsetX });\n consumeEvent(event);\n return true;\n }\n return false;\n }\n onMouseUp(event) {\n if (this._dragState) {\n consumeEvent(event);\n return true;\n }\n return false;\n }\n onClick(event) {\n if (this._dragState) {\n this._dragState = void 0;\n consumeEvent(event);\n return true;\n }\n return false;\n }\n onDblClick(event) {\n return false;\n }\n};\nvar Recorder = class {\n constructor(injectedScript) {\n this._listeners = [];\n this._lastHighlightedSelector = void 0;\n this._lastHighlightedAriaTemplateJSON = \"undefined\";\n this.state = {\n mode: \"none\",\n testIdAttributeName: \"data-testid\",\n language: \"javascript\",\n overlay: { offsetX: 0 }\n };\n this._delegate = {};\n this.document = injectedScript.document;\n this.injectedScript = injectedScript;\n this.highlight = injectedScript.createHighlight();\n this._tools = {\n \"none\": new NoneTool(),\n \"standby\": new NoneTool(),\n \"inspecting\": new InspectTool(this, false),\n \"recording\": new RecordActionTool(this),\n \"recording-inspecting\": new InspectTool(this, false),\n \"assertingText\": new TextAssertionTool(this, \"text\"),\n \"assertingVisibility\": new InspectTool(this, true),\n \"assertingValue\": new TextAssertionTool(this, \"value\"),\n \"assertingSnapshot\": new TextAssertionTool(this, \"snapshot\")\n };\n this._currentTool = this._tools.none;\n if (injectedScript.window.top === injectedScript.window) {\n this.overlay = new Overlay(this);\n this.overlay.setUIState(this.state);\n }\n this._stylesheet = new injectedScript.window.CSSStyleSheet();\n this._stylesheet.replaceSync(`\n body[data-pw-cursor=pointer] *, body[data-pw-cursor=pointer] *::after { cursor: pointer !important; }\n body[data-pw-cursor=text] *, body[data-pw-cursor=text] *::after { cursor: text !important; }\n `);\n this.installListeners();\n injectedScript.utils.cacheNormalizedWhitespaces();\n if (injectedScript.isUnderTest)\n console.error(\"Recorder script ready for test\");\n }\n installListeners() {\n var _a;\n removeEventListeners(this._listeners);\n this._listeners = [\n addEventListener(this.document, \"click\", (event) => this._onClick(event), true),\n addEventListener(this.document, \"auxclick\", (event) => this._onClick(event), true),\n addEventListener(this.document, \"dblclick\", (event) => this._onDblClick(event), true),\n addEventListener(this.document, \"contextmenu\", (event) => this._onContextMenu(event), true),\n addEventListener(this.document, \"dragstart\", (event) => this._onDragStart(event), true),\n addEventListener(this.document, \"input\", (event) => this._onInput(event), true),\n addEventListener(this.document, \"keydown\", (event) => this._onKeyDown(event), true),\n addEventListener(this.document, \"keyup\", (event) => this._onKeyUp(event), true),\n addEventListener(this.document, \"pointerdown\", (event) => this._onPointerDown(event), true),\n addEventListener(this.document, \"pointerup\", (event) => this._onPointerUp(event), true),\n addEventListener(this.document, \"mousedown\", (event) => this._onMouseDown(event), true),\n addEventListener(this.document, \"mouseup\", (event) => this._onMouseUp(event), true),\n addEventListener(this.document, \"mousemove\", (event) => this._onMouseMove(event), true),\n addEventListener(this.document, \"mouseleave\", (event) => this._onMouseLeave(event), true),\n addEventListener(this.document, \"mouseenter\", (event) => this._onMouseEnter(event), true),\n addEventListener(this.document, \"focus\", (event) => this._onFocus(event), true),\n addEventListener(this.document, \"scroll\", (event) => this._onScroll(event), true)\n ];\n this.highlight.install();\n let recreationInterval;\n const recreate = () => {\n this.highlight.install();\n recreationInterval = this.injectedScript.builtinSetTimeout(recreate, 500);\n };\n recreationInterval = this.injectedScript.builtinSetTimeout(recreate, 500);\n this._listeners.push(() => this.injectedScript.builtinClearTimeout(recreationInterval));\n this.highlight.appendChild(createSvgElement(this.document, clipPaths_default));\n (_a = this.overlay) == null ? void 0 : _a.install();\n this.document.adoptedStyleSheets.push(this._stylesheet);\n }\n _switchCurrentTool() {\n var _a, _b, _c;\n const newTool = this._tools[this.state.mode];\n if (newTool === this._currentTool)\n return;\n (_b = (_a = this._currentTool).cleanup) == null ? void 0 : _b.call(_a);\n this.clearHighlight();\n this._currentTool = newTool;\n (_c = this.injectedScript.document.body) == null ? void 0 : _c.setAttribute(\"data-pw-cursor\", newTool.cursor());\n }\n setUIState(state, delegate) {\n var _a;\n this._delegate = delegate;\n if (state.actionPoint && this.state.actionPoint && state.actionPoint.x === this.state.actionPoint.x && state.actionPoint.y === this.state.actionPoint.y) {\n } else if (!state.actionPoint && !this.state.actionPoint) {\n } else {\n if (state.actionPoint)\n this.highlight.showActionPoint(state.actionPoint.x, state.actionPoint.y);\n else\n this.highlight.hideActionPoint();\n }\n this.state = state;\n this.highlight.setLanguage(state.language);\n this._switchCurrentTool();\n (_a = this.overlay) == null ? void 0 : _a.setUIState(state);\n let highlight = \"noop\";\n if (state.actionSelector !== this._lastHighlightedSelector) {\n const model = state.actionSelector ? querySelector(this.injectedScript, state.actionSelector, this.document) : null;\n highlight = (model == null ? void 0 : model.elements.length) ? model : \"clear\";\n this._lastHighlightedSelector = (model == null ? void 0 : model.elements.length) ? state.actionSelector : void 0;\n }\n const ariaTemplateJSON = JSON.stringify(state.ariaTemplate);\n if (this._lastHighlightedAriaTemplateJSON !== ariaTemplateJSON) {\n const elements = state.ariaTemplate ? this.injectedScript.getAllByAria(this.document, state.ariaTemplate) : [];\n if (elements.length) {\n highlight = { elements };\n this._lastHighlightedAriaTemplateJSON = ariaTemplateJSON;\n } else {\n if (!this._lastHighlightedSelector)\n highlight = \"clear\";\n this._lastHighlightedAriaTemplateJSON = \"undefined\";\n }\n }\n if (highlight === \"clear\")\n this.clearHighlight();\n else if (highlight !== \"noop\")\n this._updateHighlight(highlight, false);\n }\n clearHighlight() {\n this.updateHighlight(null, false);\n }\n _onClick(event) {\n var _a, _b, _c;\n if (!event.isTrusted)\n return;\n if ((_a = this.overlay) == null ? void 0 : _a.onClick(event))\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_c = (_b = this._currentTool).onClick) == null ? void 0 : _c.call(_b, event);\n }\n _onDblClick(event) {\n var _a, _b, _c;\n if (!event.isTrusted)\n return;\n if ((_a = this.overlay) == null ? void 0 : _a.onDblClick(event))\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_c = (_b = this._currentTool).onDblClick) == null ? void 0 : _c.call(_b, event);\n }\n _onContextMenu(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onContextMenu) == null ? void 0 : _b.call(_a, event);\n }\n _onDragStart(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onDragStart) == null ? void 0 : _b.call(_a, event);\n }\n _onPointerDown(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onPointerDown) == null ? void 0 : _b.call(_a, event);\n }\n _onPointerUp(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onPointerUp) == null ? void 0 : _b.call(_a, event);\n }\n _onMouseDown(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onMouseDown) == null ? void 0 : _b.call(_a, event);\n }\n _onMouseUp(event) {\n var _a, _b, _c;\n if (!event.isTrusted)\n return;\n if ((_a = this.overlay) == null ? void 0 : _a.onMouseUp(event))\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_c = (_b = this._currentTool).onMouseUp) == null ? void 0 : _c.call(_b, event);\n }\n _onMouseMove(event) {\n var _a, _b, _c;\n if (!event.isTrusted)\n return;\n if ((_a = this.overlay) == null ? void 0 : _a.onMouseMove(event))\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_c = (_b = this._currentTool).onMouseMove) == null ? void 0 : _c.call(_b, event);\n }\n _onMouseEnter(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onMouseEnter) == null ? void 0 : _b.call(_a, event);\n }\n _onMouseLeave(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onMouseLeave) == null ? void 0 : _b.call(_a, event);\n }\n _onFocus(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onFocus) == null ? void 0 : _b.call(_a, event);\n }\n _onScroll(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n this._lastHighlightedSelector = void 0;\n this._lastHighlightedAriaTemplateJSON = \"undefined\";\n this.highlight.hideActionPoint();\n (_b = (_a = this._currentTool).onScroll) == null ? void 0 : _b.call(_a, event);\n }\n _onInput(event) {\n var _a, _b;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onInput) == null ? void 0 : _b.call(_a, event);\n }\n _onKeyDown(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onKeyDown) == null ? void 0 : _b.call(_a, event);\n }\n _onKeyUp(event) {\n var _a, _b;\n if (!event.isTrusted)\n return;\n if (this._ignoreOverlayEvent(event))\n return;\n (_b = (_a = this._currentTool).onKeyUp) == null ? void 0 : _b.call(_a, event);\n }\n updateHighlight(model, userGesture) {\n this._lastHighlightedSelector = void 0;\n this._lastHighlightedAriaTemplateJSON = \"undefined\";\n this._updateHighlight(model, userGesture);\n }\n _updateHighlight(model, userGesture) {\n var _a, _b;\n let tooltipText = model == null ? void 0 : model.tooltipText;\n if (tooltipText === void 0 && !(model == null ? void 0 : model.tooltipList) && (model == null ? void 0 : model.selector))\n tooltipText = this.injectedScript.utils.asLocator(this.state.language, model.selector);\n this.highlight.updateHighlight((model == null ? void 0 : model.elements) || [], { ...model, tooltipText });\n if (userGesture)\n (_b = (_a = this._delegate).highlightUpdated) == null ? void 0 : _b.call(_a);\n }\n _ignoreOverlayEvent(event) {\n return event.composedPath().some((e) => {\n const nodeName = e.nodeName || \"\";\n return nodeName.toLowerCase() === \"x-pw-glass\";\n });\n }\n deepEventTarget(event) {\n var _a;\n for (const element of event.composedPath()) {\n if (!((_a = this.overlay) == null ? void 0 : _a.contains(element)))\n return element;\n }\n return event.composedPath()[0];\n }\n setMode(mode) {\n var _a, _b;\n void ((_b = (_a = this._delegate).setMode) == null ? void 0 : _b.call(_a, mode));\n }\n async performAction(action) {\n var _a, _b;\n await ((_b = (_a = this._delegate).performAction) == null ? void 0 : _b.call(_a, action).catch(() => {\n }));\n }\n recordAction(action) {\n var _a, _b;\n void ((_b = (_a = this._delegate).recordAction) == null ? void 0 : _b.call(_a, action));\n }\n setOverlayState(state) {\n var _a, _b;\n void ((_b = (_a = this._delegate).setOverlayState) == null ? void 0 : _b.call(_a, state));\n }\n elementPicked(selector, model) {\n var _a, _b;\n const ariaSnapshot = this.injectedScript.ariaSnapshot(model.elements[0]);\n void ((_b = (_a = this._delegate).elementPicked) == null ? void 0 : _b.call(_a, { selector, ariaSnapshot }));\n }\n};\nvar Dialog = class {\n constructor(recorder) {\n this._dialogElement = null;\n this._recorder = recorder;\n }\n isShowing() {\n return !!this._dialogElement;\n }\n show(options) {\n const acceptButton = this._recorder.document.createElement(\"x-pw-tool-item\");\n acceptButton.title = \"Accept\";\n acceptButton.classList.add(\"accept\");\n acceptButton.appendChild(this._recorder.document.createElement(\"x-div\"));\n acceptButton.addEventListener(\"click\", () => options.onCommit());\n const cancelButton = this._recorder.document.createElement(\"x-pw-tool-item\");\n cancelButton.title = \"Close\";\n cancelButton.classList.add(\"cancel\");\n cancelButton.appendChild(this._recorder.document.createElement(\"x-div\"));\n cancelButton.addEventListener(\"click\", () => {\n var _a;\n this.close();\n (_a = options.onCancel) == null ? void 0 : _a.call(options);\n });\n this._dialogElement = this._recorder.document.createElement(\"x-pw-dialog\");\n this._keyboardListener = (event) => {\n var _a;\n if (event.key === \"Escape\") {\n this.close();\n (_a = options.onCancel) == null ? void 0 : _a.call(options);\n return;\n }\n if (event.key === \"Enter\" && (event.ctrlKey || event.metaKey)) {\n if (this._dialogElement)\n options.onCommit();\n return;\n }\n };\n this._recorder.document.addEventListener(\"keydown\", this._keyboardListener, true);\n const toolbarElement = this._recorder.document.createElement(\"x-pw-tools-list\");\n const labelElement = this._recorder.document.createElement(\"label\");\n labelElement.textContent = options.label;\n toolbarElement.appendChild(labelElement);\n toolbarElement.appendChild(this._recorder.document.createElement(\"x-spacer\"));\n toolbarElement.appendChild(acceptButton);\n toolbarElement.appendChild(cancelButton);\n this._dialogElement.appendChild(toolbarElement);\n const bodyElement = this._recorder.document.createElement(\"x-pw-dialog-body\");\n bodyElement.appendChild(options.body);\n this._dialogElement.appendChild(bodyElement);\n this._recorder.highlight.appendChild(this._dialogElement);\n return this._dialogElement;\n }\n moveTo(top, left) {\n if (!this._dialogElement)\n return;\n this._dialogElement.style.top = top + \"px\";\n this._dialogElement.style.left = left + \"px\";\n }\n close() {\n if (!this._dialogElement)\n return;\n this._dialogElement.remove();\n this._recorder.document.removeEventListener(\"keydown\", this._keyboardListener);\n this._dialogElement = null;\n }\n};\nfunction deepActiveElement(document) {\n let activeElement = document.activeElement;\n while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)\n activeElement = activeElement.shadowRoot.activeElement;\n return activeElement;\n}\nfunction modifiersForEvent(event) {\n return (event.altKey ? 1 : 0) | (event.ctrlKey ? 2 : 0) | (event.metaKey ? 4 : 0) | (event.shiftKey ? 8 : 0);\n}\nfunction buttonForEvent(event) {\n switch (event.which) {\n case 1:\n return \"left\";\n case 2:\n return \"middle\";\n case 3:\n return \"right\";\n }\n return \"left\";\n}\nfunction positionForEvent(event) {\n const targetElement = event.target;\n if (targetElement.nodeName !== \"CANVAS\")\n return;\n return {\n x: event.offsetX,\n y: event.offsetY\n };\n}\nfunction consumeEvent(e) {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n}\nfunction asCheckbox(node) {\n if (!node || node.nodeName !== \"INPUT\")\n return null;\n const inputElement = node;\n return [\"checkbox\", \"radio\"].includes(inputElement.type) ? inputElement : null;\n}\nfunction isRangeInput(node) {\n if (!node || node.nodeName !== \"INPUT\")\n return false;\n const inputElement = node;\n return inputElement.type.toLowerCase() === \"range\";\n}\nfunction addEventListener(target, eventName, listener, useCapture) {\n target.addEventListener(eventName, listener, useCapture);\n const remove = () => {\n target.removeEventListener(eventName, listener, useCapture);\n };\n return remove;\n}\nfunction removeEventListeners(listeners) {\n for (const listener of listeners)\n listener();\n listeners.splice(0, listeners.length);\n}\nfunction querySelector(injectedScript, selector, ownerDocument) {\n try {\n const parsedSelector = injectedScript.parseSelector(selector);\n return {\n selector,\n elements: injectedScript.querySelectorAll(parsedSelector, ownerDocument)\n };\n } catch (e) {\n return {\n selector,\n elements: []\n };\n }\n}\nfunction createSvgElement(doc, { tagName, attrs, children }) {\n const elem = doc.createElementNS(\"http://www.w3.org/2000/svg\", tagName);\n if (attrs) {\n for (const [k, v] of Object.entries(attrs))\n elem.setAttribute(k, v);\n }\n if (children) {\n for (const c of children)\n elem.appendChild(createSvgElement(doc, c));\n }\n return elem;\n}\n\n// packages/playwright-core/src/server/injected/recorder/pollingRecorder.ts\nvar PollingRecorder = class {\n constructor(injectedScript) {\n this._recorder = new Recorder(injectedScript);\n this._embedder = injectedScript.window;\n injectedScript.onGlobalListenersRemoved.add(() => this._recorder.installListeners());\n const refreshOverlay = () => {\n this._pollRecorderMode().catch((e) => console.log(e));\n };\n this._embedder.__pw_refreshOverlay = refreshOverlay;\n refreshOverlay();\n }\n async _pollRecorderMode() {\n const pollPeriod = 1e3;\n if (this._pollRecorderModeTimer)\n clearTimeout(this._pollRecorderModeTimer);\n const state = await this._embedder.__pw_recorderState().catch(() => null);\n if (!state) {\n this._pollRecorderModeTimer = this._recorder.injectedScript.builtinSetTimeout(() => this._pollRecorderMode(), pollPeriod);\n return;\n }\n const win = this._recorder.document.defaultView;\n if (win.top !== win) {\n state.actionPoint = void 0;\n }\n this._recorder.setUIState(state, this);\n this._pollRecorderModeTimer = this._recorder.injectedScript.builtinSetTimeout(() => this._pollRecorderMode(), pollPeriod);\n }\n async performAction(action) {\n await this._embedder.__pw_recorderPerformAction(action);\n }\n async recordAction(action) {\n await this._embedder.__pw_recorderRecordAction(action);\n }\n async elementPicked(elementInfo) {\n await this._embedder.__pw_recorderElementPicked(elementInfo);\n }\n async setMode(mode) {\n await this._embedder.__pw_recorderSetMode(mode);\n }\n async setOverlayState(state) {\n await this._embedder.__pw_recorderSetOverlayState(state);\n }\n};\nvar pollingRecorder_default = PollingRecorder;\n";

@@ -47,2 +47,4 @@ "use strict";

playwrightAPI._android._serverLauncher = new _androidServerImpl.AndroidServerLauncherImpl();
playwrightAPI._bidiChromium._serverLauncher = new _browserServerImpl.BrowserServerLauncherImpl('bidiChromium');
playwrightAPI._bidiFirefox._serverLauncher = new _browserServerImpl.BrowserServerLauncherImpl('bidiFirefox');

@@ -49,0 +51,0 @@ // Switch to async dispatch after we got Playwright object.

@@ -26,3 +26,3 @@ "use strict";

const slowMoActions = exports.slowMoActions = new Set(['Page.goBack', 'Page.goForward', 'Page.reload', 'Page.keyboardDown', 'Page.keyboardUp', 'Page.keyboardInsertText', 'Page.keyboardType', 'Page.keyboardPress', 'Page.mouseMove', 'Page.mouseDown', 'Page.mouseUp', 'Page.mouseClick', 'Page.mouseWheel', 'Page.touchscreenTap', 'Frame.blur', 'Frame.check', 'Frame.click', 'Frame.dragAndDrop', 'Frame.dblclick', 'Frame.dispatchEvent', 'Frame.fill', 'Frame.focus', 'Frame.goto', 'Frame.hover', 'Frame.press', 'Frame.selectOption', 'Frame.setInputFiles', 'Frame.tap', 'Frame.type', 'Frame.uncheck', 'ElementHandle.check', 'ElementHandle.click', 'ElementHandle.dblclick', 'ElementHandle.dispatchEvent', 'ElementHandle.fill', 'ElementHandle.focus', 'ElementHandle.hover', 'ElementHandle.press', 'ElementHandle.scrollIntoViewIfNeeded', 'ElementHandle.selectOption', 'ElementHandle.selectText', 'ElementHandle.setInputFiles', 'ElementHandle.tap', 'ElementHandle.type', 'ElementHandle.uncheck']);
const commandsWithTracingSnapshots = exports.commandsWithTracingSnapshots = new Set(['EventTarget.waitForEventInfo', 'BrowserContext.waitForEventInfo', 'Page.waitForEventInfo', 'WebSocket.waitForEventInfo', 'ElectronApplication.waitForEventInfo', 'AndroidDevice.waitForEventInfo', 'Page.emulateMedia', 'Page.goBack', 'Page.goForward', 'Page.reload', 'Page.expectScreenshot', 'Page.screenshot', 'Page.setViewportSize', 'Page.keyboardDown', 'Page.keyboardUp', 'Page.keyboardInsertText', 'Page.keyboardType', 'Page.keyboardPress', 'Page.mouseMove', 'Page.mouseDown', 'Page.mouseUp', 'Page.mouseClick', 'Page.mouseWheel', 'Page.touchscreenTap', 'Frame.evalOnSelector', 'Frame.evalOnSelectorAll', 'Frame.addScriptTag', 'Frame.addStyleTag', 'Frame.blur', 'Frame.check', 'Frame.click', 'Frame.dragAndDrop', 'Frame.dblclick', 'Frame.dispatchEvent', 'Frame.evaluateExpression', 'Frame.evaluateExpressionHandle', 'Frame.fill', 'Frame.focus', 'Frame.getAttribute', 'Frame.goto', 'Frame.hover', 'Frame.innerHTML', 'Frame.innerText', 'Frame.inputValue', 'Frame.isChecked', 'Frame.isDisabled', 'Frame.isEnabled', 'Frame.isHidden', 'Frame.isVisible', 'Frame.isEditable', 'Frame.press', 'Frame.selectOption', 'Frame.setContent', 'Frame.setInputFiles', 'Frame.tap', 'Frame.textContent', 'Frame.type', 'Frame.uncheck', 'Frame.waitForTimeout', 'Frame.waitForFunction', 'Frame.waitForSelector', 'Frame.expect', 'JSHandle.evaluateExpression', 'ElementHandle.evaluateExpression', 'JSHandle.evaluateExpressionHandle', 'ElementHandle.evaluateExpressionHandle', 'ElementHandle.evalOnSelector', 'ElementHandle.evalOnSelectorAll', 'ElementHandle.check', 'ElementHandle.click', 'ElementHandle.dblclick', 'ElementHandle.dispatchEvent', 'ElementHandle.fill', 'ElementHandle.focus', 'ElementHandle.hover', 'ElementHandle.innerHTML', 'ElementHandle.innerText', 'ElementHandle.inputValue', 'ElementHandle.isChecked', 'ElementHandle.isDisabled', 'ElementHandle.isEditable', 'ElementHandle.isEnabled', 'ElementHandle.isHidden', 'ElementHandle.isVisible', 'ElementHandle.press', 'ElementHandle.screenshot', 'ElementHandle.scrollIntoViewIfNeeded', 'ElementHandle.selectOption', 'ElementHandle.selectText', 'ElementHandle.setInputFiles', 'ElementHandle.tap', 'ElementHandle.textContent', 'ElementHandle.type', 'ElementHandle.uncheck', 'ElementHandle.waitForElementState', 'ElementHandle.waitForSelector']);
const commandsWithTracingSnapshots = exports.commandsWithTracingSnapshots = new Set(['EventTarget.waitForEventInfo', 'BrowserContext.waitForEventInfo', 'Page.waitForEventInfo', 'WebSocket.waitForEventInfo', 'ElectronApplication.waitForEventInfo', 'AndroidDevice.waitForEventInfo', 'Page.emulateMedia', 'Page.goBack', 'Page.goForward', 'Page.reload', 'Page.expectScreenshot', 'Page.screenshot', 'Page.setViewportSize', 'Page.keyboardDown', 'Page.keyboardUp', 'Page.keyboardInsertText', 'Page.keyboardType', 'Page.keyboardPress', 'Page.mouseMove', 'Page.mouseDown', 'Page.mouseUp', 'Page.mouseClick', 'Page.mouseWheel', 'Page.touchscreenTap', 'Page.accessibilitySnapshot', 'Frame.evalOnSelector', 'Frame.evalOnSelectorAll', 'Frame.addScriptTag', 'Frame.addStyleTag', 'Frame.ariaSnapshot', 'Frame.blur', 'Frame.check', 'Frame.click', 'Frame.content', 'Frame.dragAndDrop', 'Frame.dblclick', 'Frame.dispatchEvent', 'Frame.evaluateExpression', 'Frame.evaluateExpressionHandle', 'Frame.fill', 'Frame.focus', 'Frame.getAttribute', 'Frame.goto', 'Frame.hover', 'Frame.innerHTML', 'Frame.innerText', 'Frame.inputValue', 'Frame.isChecked', 'Frame.isDisabled', 'Frame.isEnabled', 'Frame.isHidden', 'Frame.isVisible', 'Frame.isEditable', 'Frame.press', 'Frame.querySelector', 'Frame.querySelectorAll', 'Frame.queryCount', 'Frame.selectOption', 'Frame.setContent', 'Frame.setInputFiles', 'Frame.tap', 'Frame.textContent', 'Frame.type', 'Frame.uncheck', 'Frame.waitForTimeout', 'Frame.waitForFunction', 'Frame.waitForSelector', 'Frame.expect', 'JSHandle.evaluateExpression', 'ElementHandle.evaluateExpression', 'JSHandle.evaluateExpressionHandle', 'ElementHandle.evaluateExpressionHandle', 'ElementHandle.evalOnSelector', 'ElementHandle.evalOnSelectorAll', 'ElementHandle.boundingBox', 'ElementHandle.check', 'ElementHandle.click', 'ElementHandle.contentFrame', 'ElementHandle.dblclick', 'ElementHandle.dispatchEvent', 'ElementHandle.fill', 'ElementHandle.focus', 'ElementHandle.hover', 'ElementHandle.innerHTML', 'ElementHandle.innerText', 'ElementHandle.inputValue', 'ElementHandle.isChecked', 'ElementHandle.isDisabled', 'ElementHandle.isEditable', 'ElementHandle.isEnabled', 'ElementHandle.isHidden', 'ElementHandle.isVisible', 'ElementHandle.press', 'ElementHandle.querySelector', 'ElementHandle.querySelectorAll', 'ElementHandle.screenshot', 'ElementHandle.scrollIntoViewIfNeeded', 'ElementHandle.selectOption', 'ElementHandle.selectText', 'ElementHandle.setInputFiles', 'ElementHandle.tap', 'ElementHandle.textContent', 'ElementHandle.type', 'ElementHandle.uncheck', 'ElementHandle.waitForElementState', 'ElementHandle.waitForSelector']);
const pausesBeforeInputActions = exports.pausesBeforeInputActions = new Set(['Frame.check', 'Frame.click', 'Frame.dragAndDrop', 'Frame.dblclick', 'Frame.fill', 'Frame.hover', 'Frame.press', 'Frame.selectOption', 'Frame.setInputFiles', 'Frame.tap', 'Frame.type', 'Frame.uncheck', 'ElementHandle.check', 'ElementHandle.click', 'ElementHandle.dblclick', 'ElementHandle.fill', 'ElementHandle.hover', 'ElementHandle.press', 'ElementHandle.selectOption', 'ElementHandle.setInputFiles', 'ElementHandle.tap', 'ElementHandle.type', 'ElementHandle.uncheck']);

@@ -46,3 +46,3 @@ "use strict";

this._options = options;
options.launchOptions = filterLaunchOptions(options.launchOptions);
options.launchOptions = filterLaunchOptions(options.launchOptions, options.allowFSPaths);
if (clientType === 'reuse-browser' || clientType === 'pre-launched-browser-or-android') (0, _utils.assert)(preLaunched.playwright);

@@ -252,3 +252,3 @@ if (clientType === 'pre-launched-browser-or-android') (0, _utils.assert)(preLaunched.browser || preLaunched.androidDevice);

}
function filterLaunchOptions(options) {
function filterLaunchOptions(options, allowFSPaths) {
return {

@@ -265,3 +265,4 @@ channel: options.channel,

slowMo: options.slowMo,
executablePath: (0, _utils.isUnderTest)() ? options.executablePath : undefined
executablePath: (0, _utils.isUnderTest)() || allowFSPaths ? options.executablePath : undefined,
downloadsPath: allowFSPaths ? options.downloadsPath : undefined
};

@@ -268,0 +269,0 @@ }

@@ -86,3 +86,4 @@ "use strict";

browserName,
launchOptions
launchOptions,
allowFSPaths: this._options.mode === 'extension'
}, {

@@ -89,0 +90,0 @@ playwright: this._preLaunchedPlaywright,

@@ -83,4 +83,4 @@ "use strict";

// Create default page as we cannot get access to the existing one.
const pageDelegate = await browser._defaultContext.newPageDelegate();
await pageDelegate.pageOrError();
const page = await browser._defaultContext.doCreateNewPage();
await page.waitForInitializedOrError();
}

@@ -133,2 +133,4 @@ return browser;

page._page._frameManager.frameAttached(event.context, parentFrameId);
const frame = page._page._frameManager.frame(event.context);
if (frame) frame._url = event.url;
return;

@@ -144,2 +146,3 @@ }

const page = new _bidiPage.BidiPage(context, session, opener || null);
page._page.mainFrame()._url = event.url;
this._bidiPages.set(event.context, page);

@@ -179,6 +182,6 @@ }

}
pages() {
return this._bidiPages().map(bidiPage => bidiPage._initializedPage).filter(Boolean);
possiblyUninitializedPages() {
return this._bidiPages().map(bidiPage => bidiPage._page);
}
async newPageDelegate() {
async doCreateNewPage() {
(0, _browserContext.assertBrowserContextIsNotOwned)(this);

@@ -191,3 +194,3 @@ const {

});
return this._browser._bidiPages.get(context);
return this._browser._bidiPages.get(context)._page;
}

@@ -194,0 +197,0 @@ async doGetCookies(urls) {

@@ -112,3 +112,22 @@ "use strict";

async getProperties(context, objectId) {
throw new Error('Method not implemented.');
const handle = this.createHandle(context, {
objectId
});
try {
const names = await handle.evaluate(object => {
const names = [];
const descriptors = Object.getOwnPropertyDescriptors(object);
for (const name in descriptors) {
var _descriptors$name;
if ((_descriptors$name = descriptors[name]) !== null && _descriptors$name !== void 0 && _descriptors$name.enumerable) names.push(name);
}
return names;
});
const values = await Promise.all(names.map(name => handle.evaluateHandle((object, name) => object[name], name)));
const map = new Map();
for (let i = 0; i < names.length; i++) map.set(names[i], values[i]);
return map;
} finally {
handle.dispose();
}
}

@@ -115,0 +134,0 @@ createHandle(context, jsRemoteObject) {

@@ -9,2 +9,3 @@ "use strict";

var _bidiKeyboard = require("./third_party/bidiKeyboard");
var _input = require("../input");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }

@@ -36,16 +37,17 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }

}
async keydown(modifiers, code, keyCode, keyCodeWithoutLocation, key, location, autoRepeat, text) {
async keydown(modifiers, keyName, description, autoRepeat) {
keyName = (0, _input.resolveSmartModifierString)(keyName);
const actions = [];
actions.push({
type: 'keyDown',
value: (0, _bidiKeyboard.getBidiKeyValue)(key)
value: (0, _bidiKeyboard.getBidiKeyValue)(keyName)
});
// TODO: add modifiers?
await this._performActions(actions);
}
async keyup(modifiers, code, keyCode, keyCodeWithoutLocation, key, location) {
async keyup(modifiers, keyName, description) {
keyName = (0, _input.resolveSmartModifierString)(keyName);
const actions = [];
actions.push({
type: 'keyUp',
value: (0, _bidiKeyboard.getBidiKeyValue)(key)
value: (0, _bidiKeyboard.getBidiKeyValue)(keyName)
});

@@ -52,0 +54,0 @@ await this._performActions(actions);

@@ -60,6 +60,8 @@ "use strict";

if (redirectedFrom) {
var _redirectedFrom$_orig;
var _redirectedFrom$_orig, _redirectedFrom$_orig2;
let params = {};
if ((_redirectedFrom$_orig = redirectedFrom._originalRequestRoute) !== null && _redirectedFrom$_orig !== void 0 && _redirectedFrom$_orig._alreadyContinuedHeaders) params = toBidiRequestHeaders((_redirectedFrom$_orig2 = redirectedFrom._originalRequestRoute._alreadyContinuedHeaders) !== null && _redirectedFrom$_orig2 !== void 0 ? _redirectedFrom$_orig2 : []);
this._session.sendMayFail('network.continueRequest', {
request: param.request.request,
...(((_redirectedFrom$_orig = redirectedFrom._originalRequestRoute) === null || _redirectedFrom$_orig === void 0 ? void 0 : _redirectedFrom$_orig._alreadyContinuedHeaders) || {})
...params
});

@@ -84,6 +86,6 @@ } else {

if (!time) return -1;
return (time - startTime) / 1000;
return time - startTime;
}
const timing = {
startTime: startTime / 1000,
startTime: startTime,
requestStart: relativeToStart(timings.requestStart),

@@ -116,3 +118,3 @@ responseStart: relativeToStart(timings.responseStart),

const isRedirected = response.status() >= 300 && response.status() <= 399;
const responseEndTime = params.request.timings.responseEnd / 1000 - response.timing().startTime;
const responseEndTime = params.request.timings.responseEnd - response.timing().startTime;
if (isRedirected) {

@@ -293,7 +295,4 @@ response._requestFinished(responseEndTime);

const bidiHeaders = toBidiHeaders(allHeaders);
const cookies = bidiHeaders.filter(h => h.name.toLowerCase() === 'cookie');
const headers = bidiHeaders.filter(h => h.name.toLowerCase() !== 'cookie');
return {
cookies,
headers
headers: bidiHeaders
};

@@ -300,0 +299,0 @@ }

@@ -44,3 +44,2 @@ "use strict";

this._page = void 0;
this._pagePromise = void 0;
this._session = void 0;

@@ -53,3 +52,2 @@ this._opener = void 0;

this._pdf = void 0;
this._initializedPage = null;
this._initScriptIds = [];

@@ -70,11 +68,9 @@ this._session = bidiSession;

// Initialize main frame.
this._pagePromise = this._initialize().finally(async () => {
await this._page.initOpener(this._opener);
}).then(() => {
this._initializedPage = this._page;
this._page.reportAsNew();
return this._page;
}).catch(e => {
this._page.reportAsNew(e);
return e;
// TODO: Wait for first execution context to be created and maybe about:blank navigated.
this._initialize().then(() => {
var _this$_opener;
return this._page.reportAsNew((_this$_opener = this._opener) === null || _this$_opener === void 0 ? void 0 : _this$_opener._page);
}, error => {
var _this$_opener2;
return this._page.reportAsNew((_this$_opener2 = this._opener) === null || _this$_opener2 === void 0 ? void 0 : _this$_opener2._page, error);
});

@@ -90,5 +86,2 @@ }

}
potentiallyUninitializedPage() {
return this._page;
}
didClose() {

@@ -99,6 +92,2 @@ this._session.dispose();

}
async pageOrError() {
// TODO: Wait for first execution context to be created and maybe about:blank navigated.
return this._pagePromise;
}
_onFrameAttached(frameId, parentFrameId) {

@@ -319,3 +308,3 @@ return this._page._frameManager.frameAttached(frameId, parentFrameId);

if (event.channel !== kPlaywrightBindingChannel) return;
const pageOrError = await this.pageOrError();
const pageOrError = await this._page.waitForInitializedOrError();
if (pageOrError instanceof Error) return;

@@ -360,3 +349,3 @@ const context = this._realmToContext.get(event.source.realm);

type: `image/${format === 'png' ? 'png' : 'jpeg'}`,
quality: quality || 80
quality: quality ? quality / 100 : 0.8
},

@@ -363,0 +352,0 @@ origin: documentRect ? 'document' : 'viewport',

@@ -16,14 +16,14 @@ "use strict";

const getBidiKeyValue = key => {
switch (key) {
const getBidiKeyValue = keyName => {
switch (keyName) {
case '\r':
case '\n':
key = 'Enter';
keyName = 'Enter';
break;
}
// Measures the number of code points rather than UTF-16 code units.
if ([...key].length === 1) {
return key;
if ([...keyName].length === 1) {
return keyName;
}
switch (key) {
switch (keyName) {
case 'Cancel':

@@ -141,2 +141,4 @@ return '\uE001';

return '\uE053';
case 'Space':
return ' ';
case 'Digit0':

@@ -237,5 +239,5 @@ return '0';

default:
throw new Error(`Unknown key: "${key}"`);
throw new Error(`Unknown key: "${keyName}"`);
}
};
exports.getBidiKeyValue = getBidiKeyValue;

@@ -105,3 +105,3 @@ "use strict";

// When PWDEBUG=1, show inspector for each context.
if ((0, _utils.debugMode)() === 'inspector') await _recorder.Recorder.show('actions', this, _recorderApp.RecorderApp.factory(this), {
if ((0, _utils.debugMode)() === 'inspector') await _recorder.Recorder.show(this, _recorderApp.RecorderApp.factory(this), {
pauseOnNextStatement: true

@@ -205,2 +205,5 @@ });

}
pages() {
return this.possiblyUninitializedPages().filter(page => page.initializedOrUndefined());
}

@@ -232,2 +235,5 @@ // BrowserContext methods.

}
hasBinding(name) {
return this._pageBindings.has(name);
}
async exposeBinding(name, needsHandle, playwrightBinding) {

@@ -272,15 +278,18 @@ if (this._pageBindings.has(name)) throw new Error(`Function "${name}" has been already registered`);

async _loadDefaultContextAsIs(progress) {
if (!this.pages().length) {
if (!this.possiblyUninitializedPages().length) {
const waitForEvent = _helper.helper.waitForEvent(progress, this, BrowserContext.Events.Page);
progress.cleanupWhenAborted(() => waitForEvent.dispose);
const page = await waitForEvent.promise;
if (page._pageIsError) throw page._pageIsError;
// Race against BrowserContext.close
await Promise.race([waitForEvent.promise, this._closePromise]);
}
const pages = this.pages();
if (pages[0]._pageIsError) throw pages[0]._pageIsError;
await pages[0].mainFrame()._waitForLoadState(progress, 'load');
return pages;
const page = this.possiblyUninitializedPages()[0];
if (!page) return;
const pageOrError = await page.waitForInitializedOrError();
if (pageOrError instanceof Error) throw pageOrError;
await page.mainFrame()._waitForLoadState(progress, 'load');
return page;
}
async _loadDefaultContext(progress) {
const pages = await this._loadDefaultContextAsIs(progress);
const defaultPage = await this._loadDefaultContextAsIs(progress);
if (!defaultPage) return;
const browserName = this._browser.options.name;

@@ -291,5 +300,4 @@ if (this._options.isMobile && browserName === 'chromium' || this._options.locale && browserName === 'webkit') {

// - webkit fails to change locale for existing page.
const oldPage = pages[0];
await this.newPage(progress.metadata);
await oldPage.close(progress.metadata);
await defaultPage.close(progress.metadata);
}

@@ -327,4 +335,4 @@ }

}
async addInitScript(source) {
const initScript = new _page6.InitScript(source);
async addInitScript(source, name) {
const initScript = new _page6.InitScript(source, false /* internal */, name);
this.initScripts.push(initScript);

@@ -389,5 +397,5 @@ await this.doAddInitScript(initScript);

async newPage(metadata) {
const pageDelegate = await this.newPageDelegate();
if (metadata.isServerSide) pageDelegate.potentiallyUninitializedPage().markAsServerSideOnly();
const pageOrError = await pageDelegate.pageOrError();
const page = await this.doCreateNewPage();
if (metadata.isServerSide) page.markAsServerSideOnly();
const pageOrError = await page.waitForInitializedOrError();
if (pageOrError instanceof _page6.Page) {

@@ -394,0 +402,0 @@ if (pageOrError.isClosed()) throw new Error('Page has been closed.');

@@ -137,3 +137,3 @@ "use strict";

async _waitForAllPagesToBeInitialized() {
await Promise.all([...this._crPages.values()].map(page => page.pageOrError()));
await Promise.all([...this._crPages.values()].map(crPage => crPage._page.waitForInitializedOrError()));
}

@@ -243,5 +243,5 @@ _onAttachedToTarget({

page.willBeginDownload();
let originPage = page._initializedPage;
let originPage = page._page.initializedOrUndefined();
// If it's a new window download, report it on the opener page.
if (!originPage && page._opener) originPage = page._opener._initializedPage;
if (!originPage && page._opener) originPage = page._opener._page.initializedOrUndefined();
if (!originPage) return;

@@ -317,6 +317,6 @@ this._downloadCreated(originPage, payload.guid, payload.url, payload.suggestedFilename);

}
pages() {
return this._crPages().map(crPage => crPage._initializedPage).filter(Boolean);
possiblyUninitializedPages() {
return this._crPages().map(crPage => crPage._page);
}
async newPageDelegate() {
async doCreateNewPage() {
(0, _browserContext.assertBrowserContextIsNotOwned)(this);

@@ -344,3 +344,3 @@ const oldKeys = this._browser.isClank() ? new Set(this._browser._crPages.keys()) : undefined;

}
return this._browser._crPages.get(targetId);
return this._browser._crPages.get(targetId)._page;
}

@@ -379,3 +379,3 @@ async doGetCookies(urls) {

async doGrantPermissions(origin, permissions) {
const webPermissionToProtocol = new Map([['geolocation', 'geolocation'], ['midi', 'midi'], ['notifications', 'notifications'], ['camera', 'videoCapture'], ['microphone', 'audioCapture'], ['background-sync', 'backgroundSync'], ['ambient-light-sensor', 'sensors'], ['accelerometer', 'sensors'], ['gyroscope', 'sensors'], ['magnetometer', 'sensors'], ['accessibility-events', 'accessibilityEvents'], ['clipboard-read', 'clipboardReadWrite'], ['clipboard-write', 'clipboardSanitizedWrite'], ['payment-handler', 'paymentHandler'],
const webPermissionToProtocol = new Map([['geolocation', 'geolocation'], ['midi', 'midi'], ['notifications', 'notifications'], ['camera', 'videoCapture'], ['microphone', 'audioCapture'], ['background-sync', 'backgroundSync'], ['ambient-light-sensor', 'sensors'], ['accelerometer', 'sensors'], ['gyroscope', 'sensors'], ['magnetometer', 'sensors'], ['clipboard-read', 'clipboardReadWrite'], ['clipboard-write', 'clipboardSanitizedWrite'], ['payment-handler', 'paymentHandler'],
// chrome-specific permissions we have.

@@ -474,3 +474,3 @@ ['midi-sysex', 'midiSysex'], ['storage-access', 'storageAccess']]);

for (const [targetId, backgroundPage] of this._browser._backgroundPages.entries()) {
if (backgroundPage._browserContext === this && backgroundPage._initializedPage) {
if (backgroundPage._browserContext === this && backgroundPage._page.initializedOrUndefined()) {
backgroundPage.didClose();

@@ -496,3 +496,3 @@ this._browser._backgroundPages.delete(targetId);

for (const backgroundPage of this._browser._backgroundPages.values()) {
if (backgroundPage._browserContext === this && backgroundPage._initializedPage) result.push(backgroundPage._initializedPage);
if (backgroundPage._browserContext === this && backgroundPage._page.initializedOrUndefined()) result.push(backgroundPage._page);
}

@@ -499,0 +499,0 @@ return result;

@@ -103,7 +103,3 @@ "use strict";

function rewriteError(error) {
if (error.message.includes('Object reference chain is too long')) return {
result: {
type: 'undefined'
}
};
if (error.message.includes('Object reference chain is too long')) throw new Error('Cannot serialize result: object reference chain is too long.');
if (error.message.includes('Object couldn\'t be returned by value')) return {

@@ -110,0 +106,0 @@ result: {

@@ -51,3 +51,9 @@ "use strict";

}
async keydown(modifiers, code, keyCode, keyCodeWithoutLocation, key, location, autoRepeat, text) {
async keydown(modifiers, keyName, description, autoRepeat) {
const {
code,
key,
location,
text
} = description;
if (code === 'Escape' && (await this._dragManger.cancelDrag())) return;

@@ -58,3 +64,3 @@ const commands = this._commandsForCode(code, modifiers);

modifiers: (0, _crProtocolHelper.toModifiersMask)(modifiers),
windowsVirtualKeyCode: keyCodeWithoutLocation,
windowsVirtualKeyCode: description.keyCodeWithoutLocation,
code,

@@ -70,3 +76,8 @@ commands,

}
async keyup(modifiers, code, keyCode, keyCodeWithoutLocation, key, location) {
async keyup(modifiers, keyName, description) {
const {
code,
key,
location
} = description;
await this._client.send('Input.dispatchKeyEvent', {

@@ -76,3 +87,3 @@ type: 'keyUp',

key,
windowsVirtualKeyCode: keyCodeWithoutLocation,
windowsVirtualKeyCode: description.keyCodeWithoutLocation,
code,

@@ -79,0 +90,0 @@ location

@@ -71,4 +71,2 @@ "use strict";

this._browserContext = void 0;
this._pagePromise = void 0;
this._initializedPage = null;
this._isBackgroundPage = void 0;

@@ -109,25 +107,11 @@ // Holds window features for the next popup being opened via window.open,

}
// Note: it is important to call |reportAsNew| before resolving pageOrError promise,
// so that anyone who awaits pageOrError got a ready and reported page.
this._pagePromise = this._mainFrameSession._initialize(bits.hasUIWindow).then(async r => {
await this._page.initOpener(this._opener);
return r;
}).catch(async e => {
await this._page.initOpener(this._opener);
throw e;
}).then(() => {
this._initializedPage = this._page;
this._reportAsNew();
return this._page;
}).catch(e => {
this._reportAsNew(e);
return e;
const createdEvent = this._isBackgroundPage ? _crBrowser.CRBrowserContext.CREvents.BackgroundPage : _browserContext.BrowserContext.Events.Page;
this._mainFrameSession._initialize(bits.hasUIWindow).then(() => {
var _this$_opener;
return this._page.reportAsNew((_this$_opener = this._opener) === null || _this$_opener === void 0 ? void 0 : _this$_opener._page, undefined, createdEvent);
}, error => {
var _this$_opener2;
return this._page.reportAsNew((_this$_opener2 = this._opener) === null || _this$_opener2 === void 0 ? void 0 : _this$_opener2._page, error, createdEvent);
});
}
potentiallyUninitializedPage() {
return this._page;
}
_reportAsNew(error) {
this._page.reportAsNew(error, this._isBackgroundPage ? _crBrowser.CRBrowserContext.CREvents.BackgroundPage : _browserContext.BrowserContext.Events.Page);
}
async _forAllFrameSessions(cb) {

@@ -160,5 +144,2 @@ const frameSessions = Array.from(this._sessions.values());

}
async pageOrError() {
return this._pagePromise;
}
didClose() {

@@ -388,2 +369,5 @@ for (const session of this._sessions.values()) session.dispose();

});
// The Promise is not always awaited (e.g. FrameSession._initialize can throw)
// so we catch errors here to prevent unhandled promise rejection.
this._firstNonInitialNavigationCommittedPromise.catch(() => {});
}

@@ -420,3 +404,3 @@ _isMainFrame() {

await this._createVideoRecorder(screencastId, screencastOptions);
this._crPage.pageOrError().then(p => {
this._crPage._page.waitForInitializedOrError().then(p => {
if (p instanceof Error) this._stopVideoRecording().catch(() => {});

@@ -622,2 +606,5 @@ });

this._page._frameManager.removeChildFramesRecursively(frame);
for (const [contextId, context] of this._contextIdToContext) {
if (context.frame === frame) this._onExecutionContextDestroyed(contextId);
}
const frameSession = new FrameSession(this._crPage, session, targetId, this);

@@ -713,3 +700,3 @@ this._crPage._sessions.set(targetId, frameSession);

async _onBindingCalled(event) {
const pageOrError = await this._crPage.pageOrError();
const pageOrError = await this._crPage._page.waitForInitializedOrError();
if (!(pageOrError instanceof Error)) {

@@ -723,2 +710,4 @@ const context = this._contextIdToContext.get(event.executionContextId);

this._page.emitOnContext(_browserContext.BrowserContext.Events.Dialog, new dialog.Dialog(this._page, event.type, event.message, async (accept, promptText) => {
// TODO: this should actually be a CDP event that notifies about a cancelled navigation attempt.
if (this._isMainFrame() && event.type === 'beforeunload' && !accept) this._page._frameManager.frameAbortedNavigation(this._page.mainFrame()._id, 'navigation cancelled by beforeunload dialog');
await this._client.send('Page.handleJavaScriptDialog', {

@@ -771,4 +760,3 @@ accept,

_willBeginDownload() {
const originPage = this._crPage._initializedPage;
if (!originPage) {
if (!this._crPage._page.initializedOrUndefined()) {
// Resume the page creation with an error. The page will automatically close right

@@ -812,3 +800,3 @@ // after the download begins.

gotFirstFrame.then(() => {
this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage.pageOrError());
this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage._page.waitForInitializedOrError());
});

@@ -815,0 +803,0 @@ }

@@ -154,3 +154,8 @@ "use strict";

var context = await browser.NewContextAsync(${formatContextOptions(options.contextOptions, options.deviceName)});`);
if (options.contextOptions.recordHar) formatter.add(` await context.RouteFromHARAsync(${quote(options.contextOptions.recordHar.path)});`);
if (options.contextOptions.recordHar) {
const url = options.contextOptions.recordHar.urlFilter;
formatter.add(` await context.RouteFromHARAsync(${quote(options.contextOptions.recordHar.path)}${url ? `, ${formatObject({
url
}, ' ', 'BrowserContextRouteFromHAROptions')}` : ''});`);
}
formatter.newLine();

@@ -180,3 +185,8 @@ return formatter.format();

{`);
if (options.contextOptions.recordHar) formatter.add(` await context.RouteFromHARAsync(${quote(options.contextOptions.recordHar.path)});`);
if (options.contextOptions.recordHar) {
const url = options.contextOptions.recordHar.urlFilter;
formatter.add(` await Context.RouteFromHARAsync(${quote(options.contextOptions.recordHar.path)}${url ? `, ${formatObject({
url
}, ' ', 'BrowserContextRouteFromHAROptions')}` : ''});`);
}
return formatter.format();

@@ -183,0 +193,0 @@ }

@@ -138,3 +138,3 @@ "use strict";

import org.junit.jupiter.api.*;
${options.contextOptions.recordHar ? `import java.nio.file.Paths;\n` : ''}import org.junit.jupiter.api.*;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.*;

@@ -146,2 +146,8 @@

void test(Page page) {`);
if (options.contextOptions.recordHar) {
const url = options.contextOptions.recordHar.urlFilter;
const recordHarOptions = typeof url === 'string' ? `, new Page.RouteFromHAROptions()
.setUrl(${quote(url)})` : '';
formatter.add(` page.routeFromHAR(Paths.get(${quote(options.contextOptions.recordHar.path)})${recordHarOptions});`);
}
return formatter.format();

@@ -153,3 +159,3 @@ }

import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import java.util.*;
${options.contextOptions.recordHar ? `import java.nio.file.Paths;\n` : ''}import java.util.*;

@@ -161,3 +167,8 @@ public class Example {

BrowserContext context = browser.newContext(${formatContextOptions(options.contextOptions, options.deviceName)});`);
if (options.contextOptions.recordHar) formatter.add(` context.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`);
if (options.contextOptions.recordHar) {
const url = options.contextOptions.recordHar.urlFilter;
const recordHarOptions = typeof url === 'string' ? `, new BrowserContext.RouteFromHAROptions()
.setUrl(${quote(url)})` : '';
formatter.add(` context.routeFromHAR(Paths.get(${quote(options.contextOptions.recordHar.path)})${recordHarOptions});`);
}
return formatter.format();

@@ -164,0 +175,0 @@ }

@@ -109,3 +109,6 @@ "use strict";

case 'assertSnapshot':
return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)}).toMatchAriaSnapshot(${quoteMultiline(action.snapshot)});`;
{
const commentIfNeeded = this._isTest ? '' : '// ';
return `${commentIfNeeded}await expect(${subject}.${this._asLocator(action.selector)}).toMatchAriaSnapshot(${quoteMultiline(action.snapshot, `${commentIfNeeded} `)});`;
}
}

@@ -131,3 +134,8 @@ }

test('test', async ({ page }) => {`);
if (options.contextOptions.recordHar) formatter.add(` await page.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`);
if (options.contextOptions.recordHar) {
const url = options.contextOptions.recordHar.urlFilter;
formatter.add(` await page.routeFromHAR(${quote(options.contextOptions.recordHar.path)}${url ? `, ${formatOptions({
url
}, false)}` : ''});`);
}
return formatter.format();

@@ -134,0 +142,0 @@ }

@@ -35,3 +35,3 @@ "use strict";

...actionInContext.action,
pageAlias: actionInContext.frame.pageAlias,
...actionInContext.frame,
locator

@@ -38,0 +38,0 @@ };

@@ -126,2 +126,3 @@ "use strict";

const formatter = new PythonFormatter();
const recordHar = options.contextOptions.recordHar;
if (this._isPyTest) {

@@ -136,3 +137,3 @@ const contextOptions = formatContextOptions(options.contextOptions, options.deviceName, true /* asDict */);

` : '';
formatter.add(`${options.deviceName ? 'import pytest\n' : ''}import re
formatter.add(`${options.deviceName || contextOptions ? 'import pytest\n' : ''}import re
from playwright.sync_api import Page, expect

@@ -142,3 +143,3 @@ ${fixture}

def test_example(page: Page) -> None {`);
if (options.contextOptions.recordHar) formatter.add(` page.route_from_har(${quote(options.contextOptions.recordHar.path)})`);
if (recordHar) formatter.add(` page.route_from_har(${quote(recordHar.path)}${typeof recordHar.urlFilter === 'string' ? `, url=${quote(recordHar.urlFilter)}` : ''})`);
} else if (this._isAsync) {

@@ -154,3 +155,3 @@ formatter.add(`

context = await browser.new_context(${formatContextOptions(options.contextOptions, options.deviceName)})`);
if (options.contextOptions.recordHar) formatter.add(` await page.route_from_har(${quote(options.contextOptions.recordHar.path)})`);
if (recordHar) formatter.add(` await context.route_from_har(${quote(recordHar.path)}${typeof recordHar.urlFilter === 'string' ? `, url=${quote(recordHar.urlFilter)}` : ''})`);
} else {

@@ -165,3 +166,3 @@ formatter.add(`

context = browser.new_context(${formatContextOptions(options.contextOptions, options.deviceName)})`);
if (options.contextOptions.recordHar) formatter.add(` context.route_from_har(${quote(options.contextOptions.recordHar.path)})`);
if (recordHar) formatter.add(` context.route_from_har(${quote(recordHar.path)}${typeof recordHar.urlFilter === 'string' ? `, url=${quote(recordHar.urlFilter)}` : ''})`);
}

@@ -168,0 +169,0 @@ return formatter.format();

@@ -12,2 +12,5 @@ "use strict";

var _utils = require("../utils");
var _utilsBundle = require("../utilsBundle");
var _locatorParser = require("../utils/isomorphic/locatorParser");
var _ariaSnapshot = require("../utils/isomorphic/ariaSnapshot");
/**

@@ -38,5 +41,2 @@ * Copyright (c) Microsoft Corporation.

}, undefined, 'DebugController');
this._autoCloseTimer = void 0;
// TODO: remove in 1.27
this._autoCloseAllowed = false;
this._trackHierarchyListener = void 0;

@@ -52,8 +52,4 @@ this._playwright = void 0;

}
setAutoCloseAllowed(allowed) {
this._autoCloseAllowed = allowed;
}
dispose() {
this.setReportStateChanged(false);
this.setAutoCloseAllowed(false);
}

@@ -63,6 +59,7 @@ setReportStateChanged(enabled) {

this._trackHierarchyListener = {
onPageOpen: () => this._emitSnapshot(),
onPageClose: () => this._emitSnapshot()
onPageOpen: () => this._emitSnapshot(false),
onPageClose: () => this._emitSnapshot(false)
};
this._playwright.instrumentation.addListener(this._trackHierarchyListener, null);
this._emitSnapshot(true);
} else if (!enabled && this._trackHierarchyListener) {

@@ -89,3 +86,2 @@ this._playwright.instrumentation.removeListener(this._trackHierarchyListener);

}
this.setAutoCloseEnabled(true);
return;

@@ -115,16 +111,11 @@ }

}
this.setAutoCloseEnabled(true);
}
async setAutoCloseEnabled(enabled) {
if (!this._autoCloseAllowed) return;
if (this._autoCloseTimer) clearTimeout(this._autoCloseTimer);
if (!enabled) return;
const heartBeat = () => {
if (!this._playwright.allPages().length) (0, _processLauncher.gracefullyProcessExitDoNotHang)(0);else this._autoCloseTimer = setTimeout(heartBeat, 5000);
};
this._autoCloseTimer = setTimeout(heartBeat, 30000);
async highlight(params) {
// Assert parameters validity.
if (params.selector) (0, _locatorParser.unsafeLocatorOrSelectorAsSelector)(this._sdkLanguage, params.selector, 'data-testid');
const ariaTemplate = params.ariaTemplate ? (0, _ariaSnapshot.parseAriaSnapshotUnsafe)(_utilsBundle.yaml, params.ariaTemplate) : undefined;
for (const recorder of await this._allRecorders()) {
if (ariaTemplate) recorder.setHighlightedAriaTemplate(ariaTemplate);else if (params.selector) recorder.setHighlightedSelector(this._sdkLanguage, params.selector);
}
}
async highlight(selector) {
for (const recorder of await this._allRecorders()) recorder.setHighlightedSelector(this._sdkLanguage, selector);
}
async hideHighlight() {

@@ -150,19 +141,5 @@ // Hide all active recorder highlights.

}
_emitSnapshot() {
const browsers = [];
let pageCount = 0;
for (const browser of this._playwright.allBrowsers()) {
const b = {
contexts: []
};
browsers.push(b);
for (const context of browser.contexts()) {
const c = {
pages: []
};
b.contexts.push(c);
for (const page of context.pages()) c.pages.push(page.mainFrame().url());
pageCount += context.pages().length;
}
}
_emitSnapshot(initial) {
const pageCount = this._playwright.allPages().length;
if (initial && !pageCount) return;
this.emit(DebugController.Events.StateChanged, {

@@ -211,3 +188,4 @@ pageCount

selector: elementInfo.selector,
locator
locator,
ariaSnapshot: elementInfo.ariaSnapshot
});

@@ -214,0 +192,0 @@ }

@@ -124,3 +124,3 @@ "use strict";

if (metadata.method === 'close') return true;
if (metadata.method === 'waitForSelector' || metadata.method === 'waitForEventInfo') return false; // Never stop on those, primarily for the test harness.
if (metadata.method === 'waitForSelector' || metadata.method === 'waitForEventInfo' || metadata.method === 'querySelector' || metadata.method === 'querySelectorAll') return false; // Never stop on those, primarily for the test harness.
const step = metadata.type + '.' + metadata.method;

@@ -127,0 +127,0 @@ // Stop before everything that generates snapshot. But don't stop before those marked as pausesBeforeInputActions

@@ -113,3 +113,3 @@ {

"Galaxy S5": {
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -125,3 +125,3 @@ "width": 360,

"Galaxy S5 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -137,3 +137,3 @@ "width": 640,

"Galaxy S8": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -149,3 +149,3 @@ "width": 360,

"Galaxy S8 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -161,3 +161,3 @@ "width": 740,

"Galaxy S9+": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -173,3 +173,3 @@ "width": 320,

"Galaxy S9+ landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -185,3 +185,3 @@ "width": 658,

"Galaxy Tab S4": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36",
"viewport": {

@@ -197,3 +197,3 @@ "width": 712,

"Galaxy Tab S4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36",
"viewport": {

@@ -1109,3 +1109,3 @@ "width": 1138,

"LG Optimus L70": {
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1121,3 +1121,3 @@ "width": 384,

"LG Optimus L70 landscape": {
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1133,3 +1133,3 @@ "width": 640,

"Microsoft Lumia 550": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36 Edge/14.14263",
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36 Edge/14.14263",
"viewport": {

@@ -1145,3 +1145,3 @@ "width": 640,

"Microsoft Lumia 550 landscape": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36 Edge/14.14263",
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36 Edge/14.14263",
"viewport": {

@@ -1157,3 +1157,3 @@ "width": 360,

"Microsoft Lumia 950": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36 Edge/14.14263",
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36 Edge/14.14263",
"viewport": {

@@ -1169,3 +1169,3 @@ "width": 360,

"Microsoft Lumia 950 landscape": {
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36 Edge/14.14263",
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36 Edge/14.14263",
"viewport": {

@@ -1181,3 +1181,3 @@ "width": 640,

"Nexus 10": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36",
"viewport": {

@@ -1193,3 +1193,3 @@ "width": 800,

"Nexus 10 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36",
"viewport": {

@@ -1205,3 +1205,3 @@ "width": 1280,

"Nexus 4": {
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1217,3 +1217,3 @@ "width": 384,

"Nexus 4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1229,3 +1229,3 @@ "width": 640,

"Nexus 5": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1241,3 +1241,3 @@ "width": 360,

"Nexus 5 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1253,3 +1253,3 @@ "width": 640,

"Nexus 5X": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1265,3 +1265,3 @@ "width": 412,

"Nexus 5X landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1277,3 +1277,3 @@ "width": 732,

"Nexus 6": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1289,3 +1289,3 @@ "width": 412,

"Nexus 6 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1301,3 +1301,3 @@ "width": 732,

"Nexus 6P": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1313,3 +1313,3 @@ "width": 412,

"Nexus 6P landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1325,3 +1325,3 @@ "width": 732,

"Nexus 7": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36",
"viewport": {

@@ -1337,3 +1337,3 @@ "width": 600,

"Nexus 7 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36",
"viewport": {

@@ -1393,3 +1393,3 @@ "width": 960,

"Pixel 2": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1405,3 +1405,3 @@ "width": 411,

"Pixel 2 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1417,3 +1417,3 @@ "width": 731,

"Pixel 2 XL": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1429,3 +1429,3 @@ "width": 411,

"Pixel 2 XL landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1441,3 +1441,3 @@ "width": 823,

"Pixel 3": {
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1453,3 +1453,3 @@ "width": 393,

"Pixel 3 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1465,3 +1465,3 @@ "width": 786,

"Pixel 4": {
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1477,3 +1477,3 @@ "width": 353,

"Pixel 4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1489,3 +1489,3 @@ "width": 745,

"Pixel 4a (5G)": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"screen": {

@@ -1505,3 +1505,3 @@ "width": 412,

"Pixel 4a (5G) landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"screen": {

@@ -1521,3 +1521,3 @@ "height": 892,

"Pixel 5": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"screen": {

@@ -1537,3 +1537,3 @@ "width": 393,

"Pixel 5 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"screen": {

@@ -1553,3 +1553,3 @@ "width": 851,

"Pixel 7": {
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"screen": {

@@ -1569,3 +1569,3 @@ "width": 412,

"Pixel 7 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"screen": {

@@ -1585,3 +1585,3 @@ "width": 915,

"Moto G4": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1597,3 +1597,3 @@ "width": 360,

"Moto G4 landscape": {
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Mobile Safari/537.36",
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Mobile Safari/537.36",
"viewport": {

@@ -1609,3 +1609,3 @@ "width": 640,

"Desktop Chrome HiDPI": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36",
"screen": {

@@ -1625,3 +1625,3 @@ "width": 1792,

"Desktop Edge HiDPI": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36 Edg/131.0.6778.33",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36 Edg/133.0.6943.16",
"screen": {

@@ -1641,3 +1641,3 @@ "width": 1792,

"Desktop Firefox HiDPI": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0",
"screen": {

@@ -1672,3 +1672,3 @@ "width": 1792,

"Desktop Chrome": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36",
"screen": {

@@ -1688,3 +1688,3 @@ "width": 1920,

"Desktop Edge": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.33 Safari/537.36 Edg/131.0.6778.33",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36 Edg/133.0.6943.16",
"screen": {

@@ -1704,3 +1704,3 @@ "width": 1920,

"Desktop Firefox": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0",
"screen": {

@@ -1707,0 +1707,0 @@ "width": 1920,

@@ -23,3 +23,2 @@ "use strict";

var _elementHandlerDispatcher = require("./elementHandlerDispatcher");
var _recorderInTraceViewer = require("../recorder/recorderInTraceViewer");
var _recorderApp = require("../recorder/recorderApp");

@@ -288,3 +287,3 @@ var _webSocketRouteDispatcher = require("./webSocketRouteDispatcher");

this._webSocketInterceptionPatterns = params.patterns;
if (params.patterns.length) await _webSocketRouteDispatcher.WebSocketRouteDispatcher.installIfNeeded(this, this._context);
if (params.patterns.length) await _webSocketRouteDispatcher.WebSocketRouteDispatcher.installIfNeeded(this._context);
}

@@ -299,13 +298,3 @@ async storageState(params, metadata) {

async enableRecorder(params) {
if (params.codegenMode === 'trace-events') {
await this._context.tracing.start({
name: 'trace',
snapshots: true,
screenshots: true,
live: true
});
await _recorder.Recorder.show('trace-events', this._context, _recorderInTraceViewer.RecorderInTraceViewer.factory(this._context), params);
} else {
await _recorder.Recorder.show('actions', this._context, _recorderApp.RecorderApp.factory(this._context), params);
}
await _recorder.Recorder.show(this._context, _recorderApp.RecorderApp.factory(this._context), params);
}

@@ -312,0 +301,0 @@ async pause(params, metadata) {

@@ -36,7 +36,9 @@ "use strict";

selector,
locator
locator,
ariaSnapshot
}) => {
this._dispatchEvent('inspectRequested', {
selector,
locator
locator,
ariaSnapshot
});

@@ -85,3 +87,3 @@ }), _utils.eventsHelper.addEventListener(this._object, _debugController.DebugController.Events.SourceChanged, ({

async highlight(params) {
await this._object.highlight(params.selector);
await this._object.highlight(params);
}

@@ -88,0 +90,0 @@ async hideHighlight() {

@@ -13,3 +13,4 @@ "use strict";

var _utils = require("../../utils");
var _ariaSnapshot = require("../ariaSnapshot");
var _ariaSnapshot = require("../../utils/isomorphic/ariaSnapshot");
var _utilsBundle = require("../../utilsBundle");
/**

@@ -280,3 +281,3 @@ * Copyright (c) Microsoft Corporation.

let expectedValue = params.expectedValue ? (0, _jsHandleDispatcher.parseArgument)(params.expectedValue) : undefined;
if (params.expression === 'to.match.aria' && expectedValue) expectedValue = (0, _ariaSnapshot.parseAriaSnapshot)(expectedValue);
if (params.expression === 'to.match.aria' && expectedValue) expectedValue = (0, _ariaSnapshot.parseAriaSnapshotUnsafe)(_utilsBundle.yaml, expectedValue);
const result = await this._frame.expect(metadata, params.selector, {

@@ -283,0 +284,0 @@ ...params,

@@ -184,3 +184,3 @@ "use strict";

this._webSocketInterceptionPatterns = params.patterns;
if (params.patterns.length) await _webSocketRouteDispatcher.WebSocketRouteDispatcher.installIfNeeded(this.parentScope(), this._page);
if (params.patterns.length) await _webSocketRouteDispatcher.WebSocketRouteDispatcher.installIfNeeded(this._page);
}

@@ -187,0 +187,0 @@ async expectScreenshot(params, metadata) {

@@ -31,4 +31,2 @@ "use strict";

function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const kBindingInstalledSymbol = Symbol('webSocketRouteBindingInstalled');
const kInitScriptInstalledSymbol = Symbol('webSocketRouteInitScriptInstalled');
class WebSocketRouteDispatcher extends _dispatcher.Dispatcher {

@@ -59,11 +57,12 @@ constructor(scope, id, url, frame) {

}
static async installIfNeeded(contextDispatcher, target) {
static async installIfNeeded(target) {
const kBindingName = '__pwWebSocketBinding';
const context = target instanceof _page.Page ? target.context() : target;
if (!context[kBindingInstalledSymbol]) {
context[kBindingInstalledSymbol] = true;
await context.exposeBinding('__pwWebSocketBinding', false, (source, payload) => {
if (!context.hasBinding(kBindingName)) {
await context.exposeBinding(kBindingName, false, (source, payload) => {
if (payload.type === 'onCreate') {
const pageDispatcher = _pageDispatcher.PageDispatcher.fromNullable(contextDispatcher, source.page);
const contextDispatcher = (0, _dispatcher.existingDispatcher)(context);
const pageDispatcher = contextDispatcher ? _pageDispatcher.PageDispatcher.fromNullable(contextDispatcher, source.page) : undefined;
let scope;
if (pageDispatcher && matchesPattern(pageDispatcher, context._options.baseURL, payload.url)) scope = pageDispatcher;else if (matchesPattern(contextDispatcher, context._options.baseURL, payload.url)) scope = contextDispatcher;
if (pageDispatcher && matchesPattern(pageDispatcher, context._options.baseURL, payload.url)) scope = pageDispatcher;else if (contextDispatcher && matchesPattern(contextDispatcher, context._options.baseURL, payload.url)) scope = contextDispatcher;
if (scope) {

@@ -101,4 +100,4 @@ new WebSocketRouteDispatcher(scope, payload.id, payload.url, source.frame);

}
if (!target[kInitScriptInstalledSymbol]) {
target[kInitScriptInstalledSymbol] = true;
const kInitScriptName = 'webSocketMockSource';
if (!target.initScripts.find(s => s.name === kInitScriptName)) {
await target.addInitScript(`

@@ -110,3 +109,3 @@ (() => {

})();
`);
`, kInitScriptName);
}

@@ -113,0 +112,0 @@ }

@@ -10,2 +10,3 @@ "use strict";

exports.kUnableToAdoptErrorMessage = void 0;
exports.throwElementIsNotAttached = throwElementIsNotAttached;
exports.throwRetargetableDOMError = throwRetargetableDOMError;

@@ -715,3 +716,4 @@ var _fs = _interopRequireDefault(require("fs"));

const result = await this.evaluateInUtility(([injected, node]) => injected.elementState(node, 'checked'), {});
return throwRetargetableDOMError(result);
if (result === 'error:notconnected' || result.received === 'error:notconnected') throwElementIsNotAttached();
return result.matches;
};

@@ -842,5 +844,8 @@ await this._markAsTargetElement(progress.metadata);

function throwRetargetableDOMError(result) {
if (result === 'error:notconnected') throw new Error('Element is not attached to the DOM');
if (result === 'error:notconnected') throwElementIsNotAttached();
return result;
}
function throwElementIsNotAttached() {
throw new Error('Element is not attached to the DOM');
}
function assertDone(result) {

@@ -847,0 +852,0 @@ // This function converts 'done' to void and ensures typescript catches unhandled errors.

@@ -135,3 +135,3 @@ "use strict";

ffPage._page._frameManager.frameAbortedNavigation(payload.frameId, 'Download is starting');
let originPage = ffPage._initializedPage;
let originPage = ffPage._page.initializedOrUndefined();
// If it's a new window download, report it on the opener page.

@@ -142,3 +142,3 @@ if (!originPage) {

ffPage._markAsError(new Error('Starting new page download'));
if (ffPage._opener) originPage = ffPage._opener._initializedPage;
if (ffPage._opener) originPage = ffPage._opener._page.initializedOrUndefined();
}

@@ -273,6 +273,6 @@ if (!originPage) return;

}
pages() {
return this._ffPages().map(ffPage => ffPage._initializedPage).filter(pageOrNull => !!pageOrNull);
possiblyUninitializedPages() {
return this._ffPages().map(ffPage => ffPage._page);
}
async newPageDelegate() {
async doCreateNewPage() {
(0, _browserContext.assertBrowserContextIsNotOwned)(this);

@@ -287,3 +287,3 @@ const {

});
return this._browser._ffPages.get(targetId);
return this._browser._ffPages.get(targetId)._page;
}

@@ -290,0 +290,0 @@ async doGetCookies(urls) {

@@ -50,8 +50,14 @@ "use strict";

}
async keydown(modifiers, code, keyCode, keyCodeWithoutLocation, key, location, autoRepeat, text) {
async keydown(modifiers, keyName, description, autoRepeat) {
let text = description.text;
// Firefox will figure out Enter by itself
if (text === '\r') text = '';
const {
code,
key,
location
} = description;
await this._client.send('Page.dispatchKeyEvent', {
type: 'keydown',
keyCode: keyCodeWithoutLocation,
keyCode: description.keyCodeWithoutLocation,
code,

@@ -64,7 +70,12 @@ key,

}
async keyup(modifiers, code, keyCode, keyCodeWithoutLocation, key, location) {
async keyup(modifiers, keyName, description) {
const {
code,
key,
location
} = description;
await this._client.send('Page.dispatchKeyEvent', {
type: 'keyup',
key,
keyCode: keyCodeWithoutLocation,
keyCode: description.keyCodeWithoutLocation,
code,

@@ -71,0 +82,0 @@ location,

@@ -18,3 +18,2 @@ "use strict";

var _debugLogger = require("../../utils/debugLogger");
var _manualPromise = require("../../utils/manualPromise");
var _browserContext = require("../browserContext");

@@ -52,5 +51,3 @@ var _errors = require("../errors");

this._browserContext = void 0;
this._pagePromise = new _manualPromise.ManualPromise();
this._initializedPage = null;
this._initializationFailed = false;
this._reportedAsNew = false;
this._opener = void 0;

@@ -75,10 +72,7 @@ this._contextIdToContext = void 0;

this._eventListeners = [_eventsHelper.eventsHelper.addEventListener(this._session, 'Page.eventFired', this._onEventFired.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.frameAttached', this._onFrameAttached.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.frameDetached', this._onFrameDetached.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.navigationAborted', this._onNavigationAborted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.navigationCommitted', this._onNavigationCommitted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.navigationStarted', this._onNavigationStarted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.sameDocumentNavigation', this._onSameDocumentNavigation.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.executionContextCreated', this._onExecutionContextCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.executionContextDestroyed', this._onExecutionContextDestroyed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.executionContextsCleared', this._onExecutionContextsCleared.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.linkClicked', event => this._onLinkClicked(event.phase)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.uncaughtError', this._onUncaughtError.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.console', this._onConsole.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.dialogOpened', this._onDialogOpened.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.bindingCalled', this._onBindingCalled.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.fileChooserOpened', this._onFileChooserOpened.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.workerCreated', this._onWorkerCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.workerDestroyed', this._onWorkerDestroyed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.dispatchMessageFromWorker', this._onDispatchMessageFromWorker.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.crashed', this._onCrashed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.videoRecordingStarted', this._onVideoRecordingStarted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketCreated', this._onWebSocketCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketClosed', this._onWebSocketClosed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketFrameReceived', this._onWebSocketFrameReceived.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketFrameSent', this._onWebSocketFrameSent.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.screencastFrame', this._onScreencastFrame.bind(this))];
this._session.once('Page.ready', async () => {
await this._page.initOpener(this._opener);
if (this._initializationFailed) return;
// Note: it is important to call |reportAsNew| before resolving pageOrError promise,
// so that anyone who awaits pageOrError got a ready and reported page.
this._initializedPage = this._page;
this._page.reportAsNew();
this._pagePromise.resolve(this._page);
this._session.once('Page.ready', () => {
var _this$_opener;
if (this._reportedAsNew) return;
this._reportedAsNew = true;
this._page.reportAsNew((_this$_opener = this._opener) === null || _this$_opener === void 0 ? void 0 : _this$_opener._page);
});

@@ -89,18 +83,9 @@ // Ideally, we somehow ensure that utility world is created before Page.ready arrives, but currently it is racy.

}
potentiallyUninitializedPage() {
return this._page;
}
async _markAsError(error) {
// Same error may be report twice: channer disconnected and session.send fails.
if (this._initializationFailed) return;
this._initializationFailed = true;
if (!this._initializedPage) {
await this._page.initOpener(this._opener);
this._page.reportAsNew(error);
this._pagePromise.resolve(error);
}
var _this$_opener2;
// Same error may be reported twice: channel disconnected and session.send fails.
if (this._reportedAsNew) return;
this._reportedAsNew = true;
this._page.reportAsNew((_this$_opener2 = this._opener) === null || _this$_opener2 === void 0 ? void 0 : _this$_opener2._page, error);
}
async pageOrError() {
return this._pagePromise;
}
_onWebSocketCreated(event) {

@@ -220,3 +205,3 @@ this._page._frameManager.onWebSocketCreated(webSocketId(event.frameId, event.wsid), event.requestURL);

async _onBindingCalled(event) {
const pageOrError = await this.pageOrError();
const pageOrError = await this._page.waitForInitializedOrError();
if (!(pageOrError instanceof Error)) {

@@ -294,3 +279,3 @@ const context = this._contextIdToContext.get(event.executionContextId);

_onVideoRecordingStarted(event) {
this._browserContext._browser._videoStarted(this._browserContext, event.screencastId, event.file, this.pageOrError());
this._browserContext._browser._videoStarted(this._browserContext, event.screencastId, event.file, this._page.waitForInitializedOrError());
}

@@ -297,0 +282,0 @@ didClose() {

@@ -199,3 +199,3 @@ "use strict";

if (this._page && page !== this._page) return;
const url = network.parsedURL(request.url());
const url = network.parseURL(request.url());
if (!url) return;

@@ -202,0 +202,0 @@ const pageEntry = this._createPageEntryIfNeeded(page);

@@ -48,8 +48,2 @@ "use strict";

});
Object.defineProperty(exports, "installDefaultBrowsersForNpmInstall", {
enumerable: true,
get: function () {
return _registry.installDefaultBrowsersForNpmInstall;
}
});
Object.defineProperty(exports, "installRootRedirect", {

@@ -56,0 +50,0 @@ enumerable: true,

@@ -43,4 +43,3 @@ "use strict";

if (kModifiers.includes(description.key)) this._pressedModifiers.add(description.key);
const text = description.text;
await this._raw.keydown(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location, autoRepeat, text);
await this._raw.keydown(this._pressedModifiers, key, description, autoRepeat);
}

@@ -65,3 +64,3 @@ _keyDescriptionForString(str) {

this._pressedKeys.delete(description.code);
await this._raw.keyup(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location);
await this._raw.keyup(this._pressedModifiers, key, description);
}

@@ -68,0 +67,0 @@ async insertText(text) {

@@ -31,3 +31,3 @@ "use strict";

async function launchApp(browserType, options) {
var _options$persistentCo, _options$persistentCo2, _options$persistentCo3;
var _options$persistentCo, _options$persistentCo2, _options$persistentCo3, _options$persistentCo4, _options$persistentCo5, _options$persistentCo6, _options$persistentCo7, _options$persistentCo8, _options$persistentCo9, _options$persistentCo10, _options$persistentCo11;
const args = [...((_options$persistentCo = (_options$persistentCo2 = options.persistentContextOptions) === null || _options$persistentCo2 === void 0 ? void 0 : _options$persistentCo2.args) !== null && _options$persistentCo !== void 0 ? _options$persistentCo : [])];

@@ -38,8 +38,8 @@ if (browserType.name() === 'chromium') {

const context = await browserType.launchPersistentContext((0, _instrumentation.serverSideCallMetadata)(), '', {
channel: !((_options$persistentCo3 = options.persistentContextOptions) !== null && _options$persistentCo3 !== void 0 && _options$persistentCo3.executablePath) ? (0, _registry.findChromiumChannel)(options.sdkLanguage) : undefined,
noDefaultViewport: true,
ignoreDefaultArgs: ['--enable-automation'],
colorScheme: 'no-override',
acceptDownloads: (0, _utils.isUnderTest)() ? 'accept' : 'internal-browser-default',
...(options === null || options === void 0 ? void 0 : options.persistentContextOptions),
channel: (_options$persistentCo3 = (_options$persistentCo4 = options.persistentContextOptions) === null || _options$persistentCo4 === void 0 ? void 0 : _options$persistentCo4.channel) !== null && _options$persistentCo3 !== void 0 ? _options$persistentCo3 : !((_options$persistentCo5 = options.persistentContextOptions) !== null && _options$persistentCo5 !== void 0 && _options$persistentCo5.executablePath) ? (0, _registry.findChromiumChannel)(options.sdkLanguage) : undefined,
noDefaultViewport: (_options$persistentCo6 = (_options$persistentCo7 = options.persistentContextOptions) === null || _options$persistentCo7 === void 0 ? void 0 : _options$persistentCo7.noDefaultViewport) !== null && _options$persistentCo6 !== void 0 ? _options$persistentCo6 : true,
acceptDownloads: (_options$persistentCo8 = options === null || options === void 0 || (_options$persistentCo9 = options.persistentContextOptions) === null || _options$persistentCo9 === void 0 ? void 0 : _options$persistentCo9.acceptDownloads) !== null && _options$persistentCo8 !== void 0 ? _options$persistentCo8 : (0, _utils.isUnderTest)() ? 'accept' : 'internal-browser-default',
colorScheme: (_options$persistentCo10 = options === null || options === void 0 || (_options$persistentCo11 = options.persistentContextOptions) === null || _options$persistentCo11 === void 0 ? void 0 : _options$persistentCo11.colorScheme) !== null && _options$persistentCo10 !== void 0 ? _options$persistentCo10 : 'no-override',
args

@@ -46,0 +46,0 @@ });

@@ -10,3 +10,3 @@ "use strict";

exports.mergeHeaders = mergeHeaders;
exports.parsedURL = parsedURL;
exports.parseURL = parseURL;
exports.rewriteCookies = rewriteCookies;

@@ -79,3 +79,3 @@ exports.singleHeader = singleHeader;

}
function parsedURL(url) {
function parseURL(url) {
try {

@@ -82,0 +82,0 @@ return new URL(url);

@@ -50,3 +50,4 @@ "use strict";

this._closedPromise = new _manualPromise.ManualPromise();
this._initialized = false;
this._initialized = void 0;
this._initializedPromise = new _manualPromise.ManualPromise();
this._eventsToEmitAfterInitialized = [];

@@ -76,3 +77,2 @@ this._crashed = false;

this._ownedContext = void 0;
this._pageIsError = void 0;
this._video = null;

@@ -101,8 +101,10 @@ this._opener = void 0;

}
async initOpener(opener) {
if (!opener) return;
const openerPage = await opener.pageOrError();
if (openerPage instanceof Page && !openerPage.isClosed()) this._opener = openerPage;
async reportAsNew(opener, error = undefined, contextEvent = _browserContext.BrowserContext.Events.Page) {
if (opener) {
const openerPageOrError = await opener.waitForInitializedOrError();
if (openerPageOrError instanceof Page && !openerPageOrError.isClosed()) this._opener = openerPageOrError;
}
this._markInitialized(error, contextEvent);
}
reportAsNew(error = undefined, contextEvent = _browserContext.BrowserContext.Events.Page) {
_markInitialized(error = undefined, contextEvent = _browserContext.BrowserContext.Events.Page) {
if (error) {

@@ -112,5 +114,5 @@ // Initialization error could have happened because of

if (this._browserContext.isClosingOrClosed()) return;
this._setIsError(error);
this._frameManager.createDummyMainFrameIfNeeded();
}
this._initialized = true;
this._initialized = error || this;
this.emitOnContext(contextEvent, this);

@@ -127,2 +129,6 @@ for (const {

if (this.isClosed()) this.emit(Page.Events.Close);else this.instrumentation.onPageOpen(this);
// Note: it is important to resolve _initializedPromise at the end,
// so that anyone who awaits waitForInitializedOrError got a ready and reported page.
this._initializedPromise.resolve(this._initialized);
}

@@ -132,2 +138,5 @@ initializedOrUndefined() {

}
waitForInitializedOrError() {
return this._initializedPromise;
}
emitOnContext(event, ...args) {

@@ -416,4 +425,4 @@ if (this._isServerSideOnly) return;

}
async addInitScript(source) {
const initScript = new InitScript(source);
async addInitScript(source, name) {
const initScript = new InitScript(source, false /* internal */, name);
this.initScripts.push(initScript);

@@ -542,6 +551,2 @@ await this._delegate.addInitScript(initScript);

}
_setIsError(error) {
this._pageIsError = error;
this._frameManager.createDummyMainFrameIfNeeded();
}
isClosed() {

@@ -792,5 +797,6 @@ return this._closedState === 'closed';

class InitScript {
constructor(source, internal) {
constructor(source, internal, name) {
this.source = void 0;
this.internal = void 0;
this.name = void 0;
const guid = (0, _utils.createGuid)();

@@ -806,2 +812,3 @@ this.source = `(() => {

this.internal = !!internal;
this.name = name;
}

@@ -808,0 +815,0 @@ }

@@ -15,3 +15,2 @@ "use strict";

var _recorderUtils = require("./recorder/recorderUtils");
var _recorderUtils2 = require("../utils/isomorphic/recorderUtils");
var _selectorParser = require("../utils/isomorphic/selectorParser");

@@ -40,3 +39,3 @@ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }

if ((0, _utils.isUnderTest)()) params.language = process.env.TEST_INSPECTOR_LANGUAGE;
return await Recorder.show('actions', context, recorderAppFactory, params);
return await Recorder.show(context, recorderAppFactory, params);
}

@@ -46,6 +45,6 @@ static showInspectorNoReply(context, recorderAppFactory) {

}
static show(codegenMode, context, recorderAppFactory, params) {
static show(context, recorderAppFactory, params) {
let recorderPromise = context[recorderSymbol];
if (!recorderPromise) {
recorderPromise = Recorder._create(codegenMode, context, recorderAppFactory, params);
recorderPromise = Recorder._create(context, recorderAppFactory, params);
context[recorderSymbol] = recorderPromise;

@@ -55,4 +54,4 @@ }

}
static async _create(codegenMode, context, recorderAppFactory, params = {}) {
const recorder = new Recorder(codegenMode, context, params);
static async _create(context, recorderAppFactory, params = {}) {
const recorder = new Recorder(context, params);
const recorderApp = await recorderAppFactory(recorder);

@@ -62,3 +61,3 @@ await recorder._install(recorderApp);

}
constructor(codegenMode, context, params) {
constructor(context, params) {
this.handleSIGINT = void 0;

@@ -81,3 +80,3 @@ this._context = void 0;

this.handleSIGINT = params.handleSIGINT;
this._contextRecorder = new _contextRecorder.ContextRecorder(codegenMode, context, params, {});
this._contextRecorder = new _contextRecorder.ContextRecorder(context, params, {});
this._context = context;

@@ -106,3 +105,3 @@ this._omitCallTracking = !!params.omitCallTracking;

if (data.params.selector) this.setHighlightedSelector(this._currentLanguage, data.params.selector);
if (data.params.ariaSnapshot) this.setHighlightedAriaSnapshot(data.params.ariaSnapshot);
if (data.params.ariaTemplate) this.setHighlightedAriaTemplate(data.params.ariaTemplate);
return;

@@ -131,2 +130,6 @@ }

}
if (data.event === 'runTask') {
this._contextRecorder.runTask(data.params.task);
return;
}
});

@@ -163,3 +166,3 @@ await Promise.all([recorderApp.setMode(this._mode), recorderApp.setPaused(this._debugger.isPaused()), this._pushAllSources()]);

actionSelector,
ariaTemplate: this._highlightedElement.ariaSnapshot,
ariaTemplate: this._highlightedElement.ariaTemplate,
language: this._currentLanguage,

@@ -177,3 +180,3 @@ testIdAttributeName: this._contextRecorder.testIdAttributeName(),

await ((_this$_recorderApp2 = this._recorderApp) === null || _this$_recorderApp2 === void 0 ? void 0 : _this$_recorderApp2.elementPicked({
selector: (0, _recorderUtils2.buildFullSelector)(selectorChain, elementInfo.selector),
selector: (0, _recorderUtils.buildFullSelector)(selectorChain, elementInfo.selector),
ariaSnapshot: elementInfo.ariaSnapshot

@@ -239,5 +242,5 @@ }, true));

}
setHighlightedAriaSnapshot(ariaSnapshot) {
setHighlightedAriaTemplate(ariaTemplate) {
this._highlightedElement = {
ariaSnapshot
ariaTemplate
};

@@ -244,0 +247,0 @@ this._refreshOverlay();

@@ -38,3 +38,3 @@ "use strict";

class ContextRecorder extends _events.EventEmitter {
constructor(codegenMode, context, params, delegate) {
constructor(context, params, delegate) {
super();

@@ -53,4 +53,2 @@ this._collection = void 0;

this._listeners = [];
this._codegenMode = void 0;
this._codegenMode = codegenMode;
this._context = context;

@@ -117,3 +115,3 @@ this._params = params;

}));
this.setEnabled(true);
this.setEnabled(params.mode === 'recording');
}

@@ -151,10 +149,2 @@ setOutput(codegenId, outputFile) {

this._collection.setEnabled(enabled);
if (this._codegenMode === 'trace-events') {
if (enabled) this._context.tracing.startChunk({
name: 'trace',
title: 'trace'
}).catch(() => {});else this._context.tracing.stopChunk({
mode: 'discard'
}).catch(() => {});
}
}

@@ -205,2 +195,5 @@ dispose() {

}
runTask(task) {
// TODO: implement
}
_describeMainFrame(page) {

@@ -297,5 +290,3 @@ return {

return selector;
} catch (e) {
return e.toString();
}
} catch (e) {}
}, (0, _utils.monotonicTime)() + 2000);

@@ -302,0 +293,0 @@ if (!result.timedOut && result.result) return result.result;

@@ -90,3 +90,3 @@ "use strict";

const mainFrame = this._page.mainFrame();
await mainFrame.goto((0, _instrumentation.serverSideCallMetadata)(), 'https://playwright/index.html');
await mainFrame.goto((0, _instrumentation.serverSideCallMetadata)(), process.env.PW_HMR ? 'http://localhost:44225' : 'https://playwright/index.html');
}

@@ -93,0 +93,0 @@ static factory(context) {

@@ -10,3 +10,2 @@ "use strict";

var _recorderUtils = require("./recorderUtils");
var _errors = require("../errors");
var _recorderRunner = require("./recorderRunner");

@@ -40,3 +39,3 @@ var _debug = require("../../utils/debug");

this._actions = [];
this._fireChange();
this.emit('change', []);
}

@@ -47,4 +46,4 @@ setEnabled(enabled) {

async performAction(actionInContext) {
await this._addAction(actionInContext, async callMetadata => {
await (0, _recorderRunner.performAction)(callMetadata, this._pageAliases, actionInContext);
await this._addAction(actionInContext, async () => {
await (0, _recorderRunner.performAction)(this._pageAliases, actionInContext);
});

@@ -67,17 +66,6 @@ }

}
const {
callMetadata,
mainFrame
} = (0, _recorderUtils.callMetadataForAction)(this._pageAliases, actionInContext);
await mainFrame.instrumentation.onBeforeCall(mainFrame, callMetadata);
this._actions.push(actionInContext);
this._fireChange();
const error = await (callback === null || callback === void 0 ? void 0 : callback(callMetadata).catch(e => e));
callMetadata.endTime = (0, _time.monotonicTime)();
actionInContext.endTime = callMetadata.endTime;
callMetadata.error = error ? (0, _errors.serializeError)(error) : undefined;
// Do not wait for onAfterCall so that performAction returned immediately after the action.
mainFrame.instrumentation.onAfterCall(mainFrame, callMetadata).then(() => {
this._fireChange();
}).catch(() => {});
await (callback === null || callback === void 0 ? void 0 : callback().catch());
actionInContext.endTime = (0, _time.monotonicTime)();
}

@@ -84,0 +72,0 @@ signal(pageAlias, frame, signal) {

@@ -10,4 +10,4 @@ "use strict";

var _language = require("../codegen/language");
var _instrumentation = require("../instrumentation");
var _recorderUtils = require("./recorderUtils");
var _recorderUtils2 = require("../../utils/isomorphic/recorderUtils");
/**

@@ -29,3 +29,4 @@ * Copyright (c) Microsoft Corporation.

async function performAction(callMetadata, pageAliases, actionInContext) {
async function performAction(pageAliases, actionInContext) {
const callMetadata = (0, _instrumentation.serverSideCallMetadata)();
const mainFrame = (0, _recorderUtils.mainFrameForAction)(pageAliases, actionInContext);

@@ -47,3 +48,3 @@ const {

}
const selector = (0, _recorderUtils2.buildFullSelector)(actionInContext.frame.framePath, action.selector);
const selector = (0, _recorderUtils.buildFullSelector)(actionInContext.frame.framePath, action.selector);
if (action.name === 'click') {

@@ -111,2 +112,5 @@ const options = toClickOptions(action);

expression: 'to.be.checked',
expectedValue: {
checked: action.checked
},
isNot: !action.checked,

@@ -113,0 +117,0 @@ timeout: kActionTimeout

@@ -6,3 +6,3 @@ "use strict";

});
exports.callMetadataForAction = callMetadataForAction;
exports.buildFullSelector = buildFullSelector;
exports.collapseActions = collapseActions;

@@ -12,4 +12,2 @@ exports.frameForAction = frameForAction;

exports.metadataToCallLog = metadataToCallLog;
var _utils = require("../../utils");
var _recorderUtils = require("../../utils/isomorphic/recorderUtils");
/**

@@ -31,2 +29,5 @@ * Copyright (c) Microsoft Corporation.

function buildFullSelector(framePath, selector) {
return [...framePath, selector].join(' >> internal:control=enter-frame >> ');
}
function metadataToCallLog(metadata, status) {

@@ -70,3 +71,3 @@ var _metadata$params, _metadata$params2, _metadata$error;

if (!page) throw new Error('Internal error: page not found');
const fullSelector = (0, _recorderUtils.buildFullSelector)(actionInContext.frame.framePath, action.selector);
const fullSelector = buildFullSelector(actionInContext.frame.framePath, action.selector);
const result = await page.mainFrame().selectors.resolveFrameForSelector(fullSelector);

@@ -76,27 +77,2 @@ if (!result) throw new Error('Internal error: frame not found');

}
function callMetadataForAction(pageAliases, actionInContext) {
const mainFrame = mainFrameForAction(pageAliases, actionInContext);
const {
method,
apiName,
params
} = (0, _recorderUtils.traceParamsForAction)(actionInContext);
const callMetadata = {
id: `call@${(0, _utils.createGuid)()}`,
apiName,
objectId: mainFrame.guid,
pageId: mainFrame._page.guid,
frameId: mainFrame.guid,
startTime: actionInContext.startTime,
endTime: 0,
type: 'Frame',
method,
params,
log: []
};
return {
callMetadata,
mainFrame
};
}
function collapseActions(actions) {

@@ -103,0 +79,0 @@ const result = [];

@@ -44,3 +44,3 @@ "use strict";

try {
const retryCount = 3;
const retryCount = 5;
for (let attempt = 1; attempt <= retryCount; ++attempt) {

@@ -47,0 +47,0 @@ _debugLogger.debugLogger.log('install', `downloading ${title} - attempt #${attempt}`);

@@ -107,3 +107,3 @@ "use strict";

if (!info) {
console.warn(`Cannot install dependencies for ${platform}!`); // eslint-disable-line no-console
console.warn(`Cannot install dependencies for ${platform} with Playwright ${(0, _userAgent.getPlaywrightVersion)()}!`); // eslint-disable-line no-console
return;

@@ -136,7 +136,7 @@ }

}
async function validateDependenciesWindows(windowsExeAndDllDirectories) {
async function validateDependenciesWindows(sdkLanguage, windowsExeAndDllDirectories) {
const directoryPaths = windowsExeAndDllDirectories;
const lddPaths = [];
for (const directoryPath of directoryPaths) lddPaths.push(...(await executablesOrSharedLibraries(directoryPath)));
const allMissingDeps = await Promise.all(lddPaths.map(lddPath => missingFileDependenciesWindows(lddPath)));
const allMissingDeps = await Promise.all(lddPaths.map(lddPath => missingFileDependenciesWindows(sdkLanguage, lddPath)));
const missingDeps = new Set();

@@ -243,4 +243,4 @@ for (const deps of allMissingDeps) {

}
async function missingFileDependenciesWindows(filePath) {
const executable = _path.default.join(__dirname, '..', '..', '..', 'bin', 'PrintDeps.exe');
async function missingFileDependenciesWindows(sdkLanguage, filePath) {
const executable = _.registry.findExecutable('winldd').executablePathOrDie(sdkLanguage);
const dirname = _path.default.dirname(filePath);

@@ -247,0 +247,0 @@ const {

@@ -11,3 +11,2 @@ "use strict";

exports.installBrowsersForNpmInstall = installBrowsersForNpmInstall;
exports.installDefaultBrowsersForNpmInstall = installDefaultBrowsersForNpmInstall;
exports.registryDirectory = exports.registry = void 0;

@@ -56,7 +55,16 @@ Object.defineProperty(exports, "writeDockerVersion", {

const BIN_PATH = _path.default.join(__dirname, '..', '..', '..', 'bin');
const PLAYWRIGHT_CDN_MIRRORS = ['https://playwright.azureedge.net', 'https://playwright-akamai.azureedge.net', 'https://playwright-verizon.azureedge.net'];
const PLAYWRIGHT_CDN_MIRRORS = ['https://cdn.playwright.dev/dbazure/download/playwright',
// ESRP CDN
'https://playwright.download.prss.microsoft.com/dbazure/download/playwright',
// Directly hit ESRP CDN
'https://cdn.playwright.dev' // Hit the Storage Bucket directly
];
if (process.env.PW_TEST_CDN_THAT_SHOULD_WORK) {
for (let i = 0; i < PLAYWRIGHT_CDN_MIRRORS.length; i++) {
const cdn = PLAYWRIGHT_CDN_MIRRORS[i];
if (cdn !== process.env.PW_TEST_CDN_THAT_SHOULD_WORK) PLAYWRIGHT_CDN_MIRRORS[i] = cdn + '.does-not-resolve.playwright.dev';
if (cdn !== process.env.PW_TEST_CDN_THAT_SHOULD_WORK) {
const parsedCDN = new URL(cdn);
parsedCDN.hostname = parsedCDN.hostname + '.does-not-resolve.playwright.dev';
PLAYWRIGHT_CDN_MIRRORS[i] = parsedCDN.toString();
}
}

@@ -89,2 +97,7 @@ }

'win': ['ffmpeg-win64.exe']
},
'winldd': {
'linux': undefined,
'mac': undefined,
'win': ['PrintDeps.exe']
}

@@ -180,2 +193,31 @@ };

},
'chromium-tip-of-tree-headless-shell': {
'<unknown>': undefined,
'ubuntu18.04-x64': undefined,
'ubuntu20.04-x64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip',
'ubuntu22.04-x64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip',
'ubuntu24.04-x64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip',
'ubuntu18.04-arm64': undefined,
'ubuntu20.04-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip',
'ubuntu22.04-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip',
'ubuntu24.04-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip',
'debian11-x64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip',
'debian11-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip',
'debian12-x64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux.zip',
'debian12-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-linux-arm64.zip',
'mac10.13': undefined,
'mac10.14': undefined,
'mac10.15': undefined,
'mac11': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac.zip',
'mac11-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac-arm64.zip',
'mac12': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac.zip',
'mac12-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac-arm64.zip',
'mac13': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac.zip',
'mac13-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac-arm64.zip',
'mac14': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac.zip',
'mac14-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac-arm64.zip',
'mac15': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac.zip',
'mac15-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-mac-arm64.zip',
'win64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-headless-shell-win64.zip'
},
'firefox': {

@@ -297,2 +339,31 @@ '<unknown>': undefined,

},
'winldd': {
'<unknown>': undefined,
'ubuntu18.04-x64': undefined,
'ubuntu20.04-x64': undefined,
'ubuntu22.04-x64': undefined,
'ubuntu24.04-x64': undefined,
'ubuntu18.04-arm64': undefined,
'ubuntu20.04-arm64': undefined,
'ubuntu22.04-arm64': undefined,
'ubuntu24.04-arm64': undefined,
'debian11-x64': undefined,
'debian11-arm64': undefined,
'debian12-x64': undefined,
'debian12-arm64': undefined,
'mac10.13': undefined,
'mac10.14': undefined,
'mac10.15': undefined,
'mac11': undefined,
'mac11-arm64': undefined,
'mac12': undefined,
'mac12-arm64': undefined,
'mac13': undefined,
'mac13-arm64': undefined,
'mac14': undefined,
'mac14-arm64': undefined,
'mac15': undefined,
'mac15-arm64': undefined,
'win64': 'builds/winldd/%s/winldd-win64.zip'
},
'android': {

@@ -360,3 +431,10 @@ '<unknown>': 'builds/android/%s/android.zip',

function readDescriptors(browsersJSON) {
return browsersJSON['browsers'].map(obj => {
const headlessShells = [];
for (const browserName of ['chromium', 'chromium-tip-of-tree']) {
headlessShells.push({
...browsersJSON.browsers.find(browser => browser.name === browserName),
name: `${browserName}-headless-shell`
});
}
return [...browsersJSON.browsers, ...headlessShells].map(obj => {
const name = obj.name;

@@ -383,3 +461,3 @@ const revisionOverride = (obj.revisionOverrides || {})[_hostPlatform.hostPlatform];

}
const allDownloadable = ['android', 'chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree', 'chromium-headless-shell'];
const allDownloadable = ['android', 'chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree', 'chromium-headless-shell', 'chromium-tip-of-tree-headless-shell'];
class Registry {

@@ -424,17 +502,2 @@ constructor(browsersJSON) {

});
this._executables.push({
type: 'channel',
name: 'chromium-next',
browserName: 'chromium',
directory: chromium.dir,
executablePath: () => chromiumExecutable,
executablePathOrDie: sdkLanguage => executablePathOrDie('chromium-next', chromiumExecutable, chromium.installByDefault, sdkLanguage),
installType: 'download-on-demand',
_validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, chromium.dir, ['chrome-linux'], [], ['chrome-win']),
downloadURLs: this._downloadURLs(chromium),
browserVersion: chromium.browserVersion,
_install: () => this._downloadExecutable(chromium, chromiumExecutable),
_dependencyGroup: 'chromium',
_isHermeticInstallation: true
});
const chromiumHeadlessShell = descriptors.find(d => d.name === 'chromium-headless-shell');

@@ -448,3 +511,3 @@ const chromiumHeadlessShellExecutable = findExecutablePath(chromiumHeadlessShell.dir, 'chromium-headless-shell');

executablePath: () => chromiumHeadlessShellExecutable,
executablePathOrDie: sdkLanguage => executablePathOrDie('chromium-headless-shell', chromiumHeadlessShellExecutable, false, sdkLanguage),
executablePathOrDie: sdkLanguage => executablePathOrDie('chromium', chromiumHeadlessShellExecutable, chromiumHeadlessShell.installByDefault, sdkLanguage),
installType: chromiumHeadlessShell.installByDefault ? 'download-by-default' : 'download-on-demand',

@@ -458,2 +521,19 @@ _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, chromiumHeadlessShell.dir, ['chrome-linux'], [], ['chrome-win']),

});
const chromiumTipOfTreeHeadlessShell = descriptors.find(d => d.name === 'chromium-tip-of-tree-headless-shell');
const chromiumTipOfTreeHeadlessShellExecutable = findExecutablePath(chromiumTipOfTreeHeadlessShell.dir, 'chromium-headless-shell');
this._executables.push({
type: 'channel',
name: 'chromium-tip-of-tree-headless-shell',
browserName: 'chromium',
directory: chromiumTipOfTreeHeadlessShell.dir,
executablePath: () => chromiumTipOfTreeHeadlessShellExecutable,
executablePathOrDie: sdkLanguage => executablePathOrDie('chromium', chromiumTipOfTreeHeadlessShellExecutable, chromiumTipOfTreeHeadlessShell.installByDefault, sdkLanguage),
installType: chromiumTipOfTreeHeadlessShell.installByDefault ? 'download-by-default' : 'download-on-demand',
_validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, chromiumTipOfTreeHeadlessShell.dir, ['chrome-linux'], [], ['chrome-win']),
downloadURLs: this._downloadURLs(chromiumTipOfTreeHeadlessShell),
browserVersion: chromium.browserVersion,
_install: () => this._downloadExecutable(chromiumTipOfTreeHeadlessShell, chromiumTipOfTreeHeadlessShellExecutable),
_dependencyGroup: 'chromium',
_isHermeticInstallation: true
});
const chromiumTipOfTree = descriptors.find(d => d.name === 'chromium-tip-of-tree');

@@ -644,2 +724,18 @@ const chromiumTipOfTreeExecutable = findExecutablePath(chromiumTipOfTree.dir, 'chromium');

});
const winldd = descriptors.find(d => d.name === 'winldd');
const winlddExecutable = findExecutablePath(winldd.dir, 'winldd');
this._executables.push({
type: 'tool',
name: 'winldd',
browserName: undefined,
directory: winldd.dir,
executablePath: () => winlddExecutable,
executablePathOrDie: sdkLanguage => executablePathOrDie('winldd', winlddExecutable, winldd.installByDefault, sdkLanguage),
installType: process.platform === 'win32' ? 'download-by-default' : 'none',
_validateHostRequirements: () => Promise.resolve(),
downloadURLs: this._downloadURLs(winldd),
_install: () => this._downloadExecutable(winldd, winlddExecutable),
_dependencyGroup: 'tools',
_isHermeticInstallation: true
});
const android = descriptors.find(d => d.name === 'android');

@@ -776,17 +872,11 @@ this._executables.push({

}
_addRequirementsAndDedupe(executables) {
const set = new Set();
for (const executable of executables) {
set.add(executable);
if (executable.browserName === 'chromium') set.add(this.findExecutable('ffmpeg'));
if (executable.name === 'chromium') set.add(this.findExecutable('chromium-headless-shell'));
}
return Array.from(set);
_dedupe(executables) {
return Array.from(new Set(executables));
}
async _validateHostRequirements(sdkLanguage, browserDirectory, linuxLddDirectories, dlOpenLibraries, windowsExeAndDllDirectories) {
if (os.platform() === 'linux') return await (0, _dependencies.validateDependenciesLinux)(sdkLanguage, linuxLddDirectories.map(d => _path.default.join(browserDirectory, d)), dlOpenLibraries);
if (os.platform() === 'win32' && os.arch() === 'x64') return await (0, _dependencies.validateDependenciesWindows)(windowsExeAndDllDirectories.map(d => _path.default.join(browserDirectory, d)));
if (os.platform() === 'win32' && os.arch() === 'x64') return await (0, _dependencies.validateDependenciesWindows)(sdkLanguage, windowsExeAndDllDirectories.map(d => _path.default.join(browserDirectory, d)));
}
async installDeps(executablesToInstallDeps, dryRun) {
const executables = this._addRequirementsAndDedupe(executablesToInstallDeps);
const executables = this._dedupe(executablesToInstallDeps);
const targets = new Set();

@@ -801,3 +891,3 @@ for (const executable of executables) {

async install(executablesToInstall, forceReinstall) {
const executables = this._addRequirementsAndDedupe(executablesToInstall);
const executables = this._dedupe(executablesToInstall);
await fs.promises.mkdir(registryDirectory, {

@@ -1048,6 +1138,2 @@ recursive: true

}
async function installDefaultBrowsersForNpmInstall() {
const defaultBrowserNames = registry.defaultExecutables().map(e => e.name);
return installBrowsersForNpmInstall(defaultBrowserNames);
}
async function installBrowsersForNpmInstall(browsers) {

@@ -1060,2 +1146,3 @@ // PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD should have a value of 0 or 1

const executables = [];
if (process.platform === 'win32') executables.push(registry.findExecutable('winldd'));
for (const browserName of browsers) {

@@ -1062,0 +1149,0 @@ const executable = registry.findExecutable(browserName);

@@ -132,3 +132,3 @@ "use strict";

firefox: ['ffmpeg', 'libasound2', 'libatk1.0-0', 'libcairo-gobject2', 'libcairo2', 'libdbus-1-3', 'libdbus-glib-1-2', 'libfontconfig1', 'libfreetype6', 'libgdk-pixbuf-2.0-0', 'libglib2.0-0', 'libgtk-3-0', 'libpango-1.0-0', 'libpangocairo-1.0-0', 'libx11-6', 'libx11-xcb1', 'libxcb-shm0', 'libxcb1', 'libxcomposite1', 'libxcursor1', 'libxdamage1', 'libxext6', 'libxfixes3', 'libxi6', 'libxrandr2', 'libxrender1', 'libxtst6'],
webkit: ['libsoup-3.0-0', 'libenchant-2-2', 'gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libicu70', 'libatk-bridge2.0-0', 'libatk1.0-0', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libegl1', 'libepoxy0', 'libevdev2', 'libffi7', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0', 'libglx0', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-3-0', 'libgudev-1.0-0', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libjpeg-turbo8', 'liblcms2-2', 'libmanette-0.2-0', 'libnotify4', 'libopengl0', 'libopenjp2-7', 'libopus0', 'libpango-1.0-0', 'libpng16-16', 'libproxy1v5', 'libsecret-1-0', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxcomposite1', 'libxdamage1', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libx264-163', 'libatomic1', 'libevent-2.1-7', 'libavif13'],
webkit: ['libsoup-3.0-0', 'libenchant-2-2', 'gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libicu70', 'libatk-bridge2.0-0', 'libatk1.0-0', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libegl1', 'libepoxy0', 'libevdev2', 'libffi7', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0', 'libglx0', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-4-1', 'libgudev-1.0-0', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libjpeg-turbo8', 'liblcms2-2', 'libmanette-0.2-0', 'libnotify4', 'libopengl0', 'libopenjp2-7', 'libopus0', 'libpango-1.0-0', 'libpng16-16', 'libproxy1v5', 'libsecret-1-0', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxcomposite1', 'libxdamage1', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libx264-163', 'libatomic1', 'libevent-2.1-7', 'libavif13'],
lib2package: {

@@ -173,2 +173,3 @@ 'libavif.so.13': 'libavif13',

'libgtk-3.so.0': 'libgtk-3-0',
'libgtk-4.so.1': 'libgtk-4-1',
'libgudev-1.0.so.0': 'libgudev-1.0-0',

@@ -230,3 +231,3 @@ 'libharfbuzz-icu.so.0': 'libharfbuzz-icu0',

firefox: ['libasound2t64', 'libatk1.0-0t64', 'libcairo-gobject2', 'libcairo2', 'libdbus-1-3', 'libfontconfig1', 'libfreetype6', 'libgdk-pixbuf-2.0-0', 'libglib2.0-0t64', 'libgtk-3-0t64', 'libpango-1.0-0', 'libpangocairo-1.0-0', 'libx11-6', 'libx11-xcb1', 'libxcb-shm0', 'libxcb1', 'libxcomposite1', 'libxcursor1', 'libxdamage1', 'libxext6', 'libxfixes3', 'libxi6', 'libxrandr2', 'libxrender1'],
webkit: ['gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libicu74', 'libatomic1', 'libatk-bridge2.0-0t64', 'libatk1.0-0t64', 'libcairo-gobject2', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libenchant-2-2', 'libepoxy0', 'libevent-2.1-7t64', 'libflite1', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0t64', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-bad1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-3-0t64', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libicu74', 'libjpeg-turbo8', 'liblcms2-2', 'libmanette-0.2-0', 'libopus0', 'libpango-1.0-0', 'libpangocairo-1.0-0', 'libpng16-16t64', 'libsecret-1-0', 'libvpx9', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebp7', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libx264-164', 'libavif16'],
webkit: ['gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libicu74', 'libatomic1', 'libatk-bridge2.0-0t64', 'libatk1.0-0t64', 'libcairo-gobject2', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libenchant-2-2', 'libepoxy0', 'libevent-2.1-7t64', 'libflite1', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0t64', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-bad1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-4-1', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libicu74', 'libjpeg-turbo8', 'liblcms2-2', 'libmanette-0.2-0', 'libopus0', 'libpango-1.0-0', 'libpangocairo-1.0-0', 'libpng16-16t64', 'libsecret-1-0', 'libvpx9', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebp7', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libx264-164', 'libavif16'],
lib2package: {

@@ -282,2 +283,3 @@ 'libavif.so.16': 'libavif16',

'libgtk-3.so.0': 'libgtk-3-0t64',
'libgtk-4.so.1': 'libgtk-4-1',
'libharfbuzz-icu.so.0': 'libharfbuzz-icu0',

@@ -421,3 +423,3 @@ 'libharfbuzz.so.0': 'libharfbuzz0b',

firefox: ['libasound2', 'libatk1.0-0', 'libcairo-gobject2', 'libcairo2', 'libdbus-1-3', 'libdbus-glib-1-2', 'libfontconfig1', 'libfreetype6', 'libgdk-pixbuf-2.0-0', 'libglib2.0-0', 'libgtk-3-0', 'libharfbuzz0b', 'libpango-1.0-0', 'libpangocairo-1.0-0', 'libx11-6', 'libx11-xcb1', 'libxcb-shm0', 'libxcb1', 'libxcomposite1', 'libxcursor1', 'libxdamage1', 'libxext6', 'libxfixes3', 'libxi6', 'libxrandr2', 'libxrender1', 'libxtst6'],
webkit: ['libsoup-3.0-0', 'gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libatk-bridge2.0-0', 'libatk1.0-0', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libegl1', 'libenchant-2-2', 'libepoxy0', 'libevdev2', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0', 'libglx0', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-3-0', 'libgudev-1.0-0', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libicu72', 'libjpeg62-turbo', 'liblcms2-2', 'libmanette-0.2-0', 'libnotify4', 'libopengl0', 'libopenjp2-7', 'libopus0', 'libpango-1.0-0', 'libpng16-16', 'libproxy1v5', 'libsecret-1-0', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebp7', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxcomposite1', 'libxdamage1', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libatomic1', 'libevent-2.1-7', 'libavif15'],
webkit: ['libsoup-3.0-0', 'gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libatk-bridge2.0-0', 'libatk1.0-0', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libegl1', 'libenchant-2-2', 'libepoxy0', 'libevdev2', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0', 'libglx0', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-4-1', 'libgudev-1.0-0', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libicu72', 'libjpeg62-turbo', 'liblcms2-2', 'libmanette-0.2-0', 'libnotify4', 'libopengl0', 'libopenjp2-7', 'libopus0', 'libpango-1.0-0', 'libpng16-16', 'libproxy1v5', 'libsecret-1-0', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebp7', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxcomposite1', 'libxdamage1', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libatomic1', 'libevent-2.1-7', 'libavif15'],
lib2package: {

@@ -450,3 +452,4 @@ 'libavif.so.15': 'libavif15',

'libxkbcommon.so.0': 'libxkbcommon0',
'libXrandr.so.2': 'libxrandr2'
'libXrandr.so.2': 'libxrandr2',
'libgtk-4.so.1': 'libgtk-4-1'
}

@@ -453,0 +456,0 @@ }

@@ -38,2 +38,4 @@ "use strict";

const kCurrentSrcAttribute = '__playwright_current_src__';
const kBoundingRectAttribute = '__playwright_bounding_rect__';
const kPopoverOpenAttribute = '__playwright_popover_open_';

@@ -357,2 +359,20 @@ // Symbols for our own info on Nodes/StyleSheets.

}
if (nodeName === 'CANVAS' || nodeName === 'IFRAME' || nodeName === 'FRAME') {
const boundingRect = element.getBoundingClientRect();
const value = JSON.stringify({
left: boundingRect.left,
top: boundingRect.top,
right: boundingRect.right,
bottom: boundingRect.bottom
});
expectValue(kBoundingRectAttribute);
expectValue(value);
attrs[kBoundingRectAttribute] = value;
}
if (element.popover && element.matches && element.matches(':popover-open')) {
const value = 'true';
expectValue(kPopoverOpenAttribute);
expectValue(value);
attrs[kPopoverOpenAttribute] = value;
}
if (element.scrollTop) {

@@ -359,0 +379,0 @@ expectValue(kScrollTopAttribute);

@@ -97,3 +97,8 @@ "use strict";

for (const reporter of options.reporter || []) params.append('reporter', reporter);
const urlPath = `./trace/${options.webApp || 'index.html'}?${params.toString()}`;
let baseUrl = '.';
if (process.env.PW_HMR) {
baseUrl = 'http://localhost:44223'; // port is hardcoded in build.js
params.set('server', server.urlPrefix('precise'));
}
const urlPath = `${baseUrl}/trace/${options.webApp || 'index.html'}?${params.toString()}`;
server.routePath('/', (_, response) => {

@@ -100,0 +105,0 @@ response.statusCode = 302;

@@ -28,2 +28,3 @@ "use strict";

const perMessageDeflate = exports.perMessageDeflate = {
clientNoContextTakeover: true,
zlibDeflateOptions: {

@@ -30,0 +31,0 @@ level: 3

@@ -45,3 +45,3 @@ "use strict";

if (!error.logs) return error;
if (error.logs.includes('cannot open display')) error.logs = '\n' + (0, _utils.wrapInASCIIBox)(_browserType.kNoXServerRunningError, 1);
if (error.logs.includes('Failed to open display') || error.logs.includes('cannot open display')) error.logs = '\n' + (0, _utils.wrapInASCIIBox)(_browserType.kNoXServerRunningError, 1);
return error;

@@ -48,0 +48,0 @@ }

@@ -111,3 +111,3 @@ "use strict";

page._page._frameManager.frameAbortedNavigation(payload.frameId, 'Download is starting');
let originPage = page._initializedPage;
let originPage = page._page.initializedOrUndefined();
// If it's a new window download, report it on the opener page.

@@ -118,3 +118,3 @@ if (!originPage) {

page._firstNonInitialNavigationCommittedReject(new Error('Starting new page download'));
if (page._opener) originPage = page._opener._initializedPage;
if (page._opener) originPage = page._opener._page.initializedOrUndefined();
}

@@ -214,6 +214,6 @@ if (!originPage) return;

}
pages() {
return this._wkPages().map(wkPage => wkPage._initializedPage).filter(pageOrNull => !!pageOrNull);
possiblyUninitializedPages() {
return this._wkPages().map(wkPage => wkPage._page);
}
async newPageDelegate() {
async doCreateNewPage() {
(0, _browserContext.assertBrowserContextIsNotOwned)(this);

@@ -225,3 +225,3 @@ const {

});
return this._browser._wkPages.get(pageProxyId);
return this._browser._wkPages.get(pageProxyId)._page;
}

@@ -228,0 +228,0 @@ async doGetCookies(urls) {

@@ -114,2 +114,3 @@ "use strict";

function rewriteError(error) {
if (error.message.includes('Object has too long reference chain')) throw new Error('Cannot serialize result: object reference chain is too long.');
if (!js.isJavaScriptErrorInEvaluate(error) && !(0, _protocolError.isSessionClosedError)(error)) return new Error('Execution context was destroyed, most likely because of a navigation.');

@@ -116,0 +117,0 @@ return error;

@@ -54,3 +54,3 @@ "use strict";

}
async keydown(modifiers, code, keyCode, keyCodeWithoutLocation, key, location, autoRepeat, text) {
async keydown(modifiers, keyName, description, autoRepeat) {
const parts = [];

@@ -60,2 +60,8 @@ for (const modifier of ['Shift', 'Control', 'Alt', 'Meta']) {

}
const {
code,
keyCode,
key,
text
} = description;
parts.push(code);

@@ -75,6 +81,10 @@ const shortcut = parts.join('+');

macCommands: commands,
isKeypad: location === input.keypadLocation
isKeypad: description.location === input.keypadLocation
});
}
async keyup(modifiers, code, keyCode, keyCodeWithoutLocation, key, location) {
async keyup(modifiers, keyName, description) {
const {
code,
key
} = description;
await this._pageProxySession.send('Input.dispatchKeyEvent', {

@@ -84,5 +94,5 @@ type: 'keyUp',

key,
windowsVirtualKeyCode: keyCode,
windowsVirtualKeyCode: description.keyCode,
code,
isKeypad: location === input.keypadLocation
isKeypad: description.location === input.keypadLocation
});

@@ -89,0 +99,0 @@ }

@@ -8,3 +8,2 @@ "use strict";

var _path = _interopRequireDefault(require("path"));
var _os = _interopRequireDefault(require("os"));
var _utilsBundle = require("../../utilsBundle");

@@ -28,3 +27,2 @@ var _stackTrace = require("../../utils/stackTrace");

var _debugLogger = require("../../utils/debugLogger");
var _manualPromise = require("../../utils/manualPromise");
var _browserContext = require("../browserContext");

@@ -61,3 +59,2 @@ var _errors = require("../errors");

this._page = void 0;
this._pagePromise = new _manualPromise.ManualPromise();
this._pageProxySession = void 0;

@@ -72,3 +69,2 @@ this._opener = void 0;

this._browserContext = void 0;
this._initializedPage = null;
this._firstNonInitialNavigationCommittedPromise = void 0;

@@ -110,5 +106,2 @@ this._firstNonInitialNavigationCommittedFulfill = () => {};

}
potentiallyUninitializedPage() {
return this._page;
}
async _initializePageProxySession() {

@@ -311,3 +304,3 @@ if (this._page._browserContext.isSettingStorageState()) return;

handleProvisionalLoadFailed(event) {
if (!this._initializedPage) {
if (!this._page.initializedOrUndefined()) {
this._firstNonInitialNavigationCommittedReject(new Error('Initial load failed'));

@@ -325,5 +318,2 @@ return;

}
async pageOrError() {
return this._pagePromise;
}
async _onTargetCreated(event) {

@@ -348,3 +338,4 @@ const {

if (!targetInfo.isProvisional) {
(0, _utils.assert)(!this._initializedPage);
var _this$_opener;
(0, _utils.assert)(!this._page.initializedOrUndefined());
let pageOrError;

@@ -376,8 +367,3 @@ try {

}
await this._page.initOpener(this._opener);
// Note: it is important to call |reportAsNew| before resolving pageOrError promise,
// so that anyone who awaits pageOrError got a ready and reported page.
this._initializedPage = pageOrError instanceof _page.Page ? pageOrError : null;
this._page.reportAsNew(pageOrError instanceof _page.Page ? undefined : pageOrError);
this._pagePromise.resolve(pageOrError);
this._page.reportAsNew((_this$_opener = this._opener) === null || _this$_opener === void 0 ? void 0 : _this$_opener._page, pageOrError instanceof _page.Page ? undefined : pageOrError);
} else {

@@ -485,3 +471,3 @@ (0, _utils.assert)(targetInfo.isProvisional);

async _onBindingCalled(contextId, argument) {
const pageOrError = await this.pageOrError();
const pageOrError = await this._page.waitForInitializedOrError();
if (!(pageOrError instanceof Error)) {

@@ -583,2 +569,4 @@ const context = this._contextIdToContext.get(contextId);

this._page.emitOnContext(_browserContext.BrowserContext.Events.Dialog, new dialog.Dialog(this._page, event.type, event.message, async (accept, promptText) => {
// TODO: this should actually be a RDP event that notifies about a cancelled navigation attempt.
if (event.type === 'beforeunload' && !accept) this._page._frameManager.frameAbortedNavigation(this._page.mainFrame()._id, 'navigation cancelled by beforeunload dialog');
await this._pageProxySession.send('Dialog.handleJavaScriptDialog', {

@@ -704,8 +692,4 @@ accept,

const angle = viewportSize.width > viewportSize.height ? 90 : 0;
// Special handling for macOS 12.
const useLegacySetOrientationOverrideMethod = _os.default.platform() === 'darwin' && parseInt(_os.default.release().split('.')[0], 10) <= 21;
if (useLegacySetOrientationOverrideMethod) promises.push(this._session.send('Page.setOrientationOverride', {
promises.push(this._pageProxySession.send('Emulation.setOrientationOverride', {
angle
}));else promises.push(this._pageProxySession.send('Emulation.setOrientationOverride', {
angle
}));

@@ -819,3 +803,3 @@ }

this._recordingVideoFile = options.outputFile;
this._browserContext._browser._videoStarted(this._browserContext, screencastId, options.outputFile, this.pageOrError());
this._browserContext._browser._videoStarted(this._browserContext, screencastId, options.outputFile, this._page.waitForInitializedOrError());
}

@@ -822,0 +806,0 @@ async _stopVideo() {

@@ -6,2 +6,3 @@ "use strict";

});
exports.compareBuffersOrStrings = compareBuffersOrStrings;
exports.getComparator = getComparator;

@@ -115,16 +116,21 @@ var _utilsBundle = require("../utilsBundle");

};
const expected = expectedBuffer.toString('utf-8');
let expected = expectedBuffer.toString('utf-8');
if (expected === actual) return null;
const diffs = _utilsBundle.diff.diffChars(expected, actual);
// Eliminate '\\ No newline at end of file'
if (!actual.endsWith('\n')) actual += '\n';
if (!expected.endsWith('\n')) expected += '\n';
const lines = _utilsBundle.diff.createPatch('file', expected, actual, undefined, undefined, {
context: 5
}).split('\n');
const coloredLines = lines.slice(4).map(line => {
if (line.startsWith('-')) return _utilsBundle.colors.red(line);
if (line.startsWith('+')) return _utilsBundle.colors.green(line);
if (line.startsWith('@@')) return _utilsBundle.colors.dim(line);
return line;
});
const errorMessage = coloredLines.join('\n');
return {
errorMessage: diff_prettyTerminal(diffs)
errorMessage
};
}
function diff_prettyTerminal(diffs) {
const result = diffs.map(part => {
const text = part.value;
if (part.added) return _utilsBundle.colors.green(text);else if (part.removed) return _utilsBundle.colors.reset(_utilsBundle.colors.strikethrough(_utilsBundle.colors.red(text)));else return text;
});
return result.join('');
}
function resizeImage(image, size) {

@@ -131,0 +137,0 @@ if (image.width === size.width && image.height === size.height) return image;

@@ -49,3 +49,5 @@ "use strict";

// green
'server:metadata': 33 // blue
'server:metadata': 33,
// blue,
'recorder': 45 // cyan
};

@@ -52,0 +54,0 @@ class DebugLogger {

@@ -69,19 +69,25 @@ "use strict";

if ((distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'ubuntu' || (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'pop' || (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'neon' || (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'tuxedo') {
const isOfficiallySupportedPlatform = (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'ubuntu';
if (parseInt(distroInfo.version, 10) <= 19) return {
const isUbuntu = (distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.id) === 'ubuntu';
const version = distroInfo === null || distroInfo === void 0 ? void 0 : distroInfo.version;
const major = parseInt(distroInfo.version, 10);
if (major < 20) return {
hostPlatform: 'ubuntu18.04' + archSuffix,
isOfficiallySupportedPlatform: false
};
if (parseInt(distroInfo.version, 10) <= 21) return {
if (major < 22) return {
hostPlatform: 'ubuntu20.04' + archSuffix,
isOfficiallySupportedPlatform
isOfficiallySupportedPlatform: isUbuntu && version === '20.04'
};
if (parseInt(distroInfo.version, 10) <= 22) return {
if (major < 24) return {
hostPlatform: 'ubuntu22.04' + archSuffix,
isOfficiallySupportedPlatform
isOfficiallySupportedPlatform: isUbuntu && version === '22.04'
};
return {
if (major < 26) return {
hostPlatform: 'ubuntu24.04' + archSuffix,
isOfficiallySupportedPlatform
isOfficiallySupportedPlatform: isUbuntu && version === '24.04'
};
return {
hostPlatform: 'ubuntu' + distroInfo.version + archSuffix,
isOfficiallySupportedPlatform: false
};
}

@@ -88,0 +94,0 @@ // Linux Mint is ubuntu-based but does not have the same versions

@@ -6,5 +6,6 @@ "use strict";

});
exports.AriaKeyError = void 0;
exports.parseAriaKey = parseAriaKey;
exports.parseYamlTemplate = parseYamlTemplate;
exports.ParserError = exports.KeyParser = void 0;
exports.parseAriaSnapshot = parseAriaSnapshot;
exports.parseAriaSnapshotUnsafe = parseAriaSnapshotUnsafe;
exports.valueOrRegex = valueOrRegex;
/**

@@ -28,43 +29,102 @@ * Copyright (c) Microsoft Corporation.

function parseYamlTemplate(fragment) {
const result = {
kind: 'role',
role: 'fragment'
// We pass parsed template between worlds using JSON, make it easy.
function parseAriaSnapshotUnsafe(yaml, text) {
const result = parseAriaSnapshot(yaml, text);
if (result.errors.length) throw new Error(result.errors[0].message);
return result.fragment;
}
function parseAriaSnapshot(yaml, text, options = {}) {
var _fragment$children;
const lineCounter = new yaml.LineCounter();
const parseOptions = {
keepSourceTokens: true,
lineCounter,
...options
};
populateNode(result, fragment);
if (result.children && result.children.length === 1) return result.children[0];
return result;
}
function populateNode(node, container) {
for (const object of container) {
if (typeof object === 'string') {
const childNode = KeyParser.parse(object);
node.children = node.children || [];
node.children.push(childNode);
continue;
const yamlDoc = yaml.parseDocument(text, parseOptions);
const errors = [];
const convertRange = range => {
return [lineCounter.linePos(range[0]), lineCounter.linePos(range[1])];
};
const addError = error => {
errors.push({
message: error.message,
range: [lineCounter.linePos(error.pos[0]), lineCounter.linePos(error.pos[1])]
});
};
const convertSeq = (container, seq) => {
for (const item of seq.items) {
const itemIsString = item instanceof yaml.Scalar && typeof item.value === 'string';
if (itemIsString) {
const childNode = KeyParser.parse(item, parseOptions, errors);
if (childNode) {
container.children = container.children || [];
container.children.push(childNode);
}
continue;
}
const itemIsMap = item instanceof yaml.YAMLMap;
if (itemIsMap) {
convertMap(container, item);
continue;
}
errors.push({
message: 'Sequence items should be strings or maps',
range: convertRange(item.range || seq.range)
});
}
for (const key of Object.keys(object)) {
node.children = node.children || [];
const value = object[key];
if (key === 'text') {
node.children.push({
kind: 'text',
text: valueOrRegex(value)
};
const convertMap = (container, map) => {
for (const entry of map.items) {
container.children = container.children || [];
// Key must by a string
const keyIsString = entry.key instanceof yaml.Scalar && typeof entry.key.value === 'string';
if (!keyIsString) {
errors.push({
message: 'Only string keys are supported',
range: convertRange(entry.key.range || map.range)
});
continue;
}
const childNode = KeyParser.parse(key);
if (childNode.kind === 'text') {
node.children.push({
const key = entry.key;
const value = entry.value;
// - text: "text"
if (key.value === 'text') {
const valueIsString = value instanceof yaml.Scalar && typeof value.value === 'string';
if (!valueIsString) {
errors.push({
message: 'Text value should be a string',
range: convertRange(entry.value.range || map.range)
});
continue;
}
container.children.push({
kind: 'text',
text: valueOrRegex(value)
text: valueOrRegex(value.value)
});
continue;
}
if (typeof value === 'string') {
node.children.push({
// role "name": ...
const childNode = KeyParser.parse(key, parseOptions, errors);
if (!childNode) continue;
// - role "name": "text"
const valueIsScalar = value instanceof yaml.Scalar;
if (valueIsScalar) {
const type = typeof value.value;
if (type !== 'string' && type !== 'number' && type !== 'boolean') {
errors.push({
message: 'Node value should be a string or a sequence',
range: convertRange(entry.value.range || map.range)
});
continue;
}
container.children.push({
...childNode,
children: [{
kind: 'text',
text: valueOrRegex(value)
text: valueOrRegex(String(value.value))
}]

@@ -74,7 +134,60 @@ });

}
node.children.push(childNode);
populateNode(childNode, value);
// - role "name":
// - child
const valueIsSequence = value instanceof yaml.YAMLSeq;
if (valueIsSequence) {
container.children.push(childNode);
convertSeq(childNode, value);
continue;
}
errors.push({
message: 'Map values should be strings or sequences',
range: convertRange(entry.value.range || map.range)
});
}
};
const fragment = {
kind: 'role',
role: 'fragment'
};
yamlDoc.errors.forEach(addError);
if (errors.length) return {
errors,
fragment
};
if (!(yamlDoc.contents instanceof yaml.YAMLSeq)) {
errors.push({
message: 'Aria snapshot must be a YAML sequence, elements starting with " -"',
range: yamlDoc.contents ? convertRange(yamlDoc.contents.range) : [{
line: 0,
col: 0
}, {
line: 0,
col: 0
}]
});
}
if (errors.length) return {
errors,
fragment
};
convertSeq(fragment, yamlDoc.contents);
if (errors.length) return {
errors,
fragment: emptyFragment
};
if (((_fragment$children = fragment.children) === null || _fragment$children === void 0 ? void 0 : _fragment$children.length) === 1) return {
fragment: fragment.children[0],
errors
};
return {
fragment,
errors
};
}
const emptyFragment = {
kind: 'role',
role: 'fragment'
};
function normalizeWhitespace(text) {

@@ -84,7 +197,21 @@ return text.replace(/[\r\n\s\t]+/g, ' ').trim();

function valueOrRegex(value) {
return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : normalizeWhitespace(value);
return value.startsWith('/') && value.endsWith('/') && value.length > 1 ? {
pattern: value.slice(1, -1)
} : normalizeWhitespace(value);
}
class KeyParser {
static parse(input) {
return new KeyParser(input)._parse();
static parse(text, options, errors) {
try {
return new KeyParser(text.value)._parse();
} catch (e) {
if (e instanceof ParserError) {
const message = options.prettyErrors === false ? e.message : e.message + ':\n\n' + text.value + '\n' + ' '.repeat(e.pos) + '^\n';
errors.push({
message,
range: [options.lineCounter.linePos(text.range[0]), options.lineCounter.linePos(text.range[0] + e.pos)]
});
return null;
}
throw e;
}
}

@@ -139,4 +266,4 @@ constructor(input) {

}
_throwError(message, pos) {
throw new AriaKeyError(message, this._input, pos || this._pos);
_throwError(message, offset = 0) {
throw new ParserError(message, offset || this._pos);
}

@@ -156,3 +283,5 @@ _readRegex() {

} else if (ch === '/' && !insideClass) {
return result;
return {
pattern: result
};
} else if (ch === '[') {

@@ -174,7 +303,7 @@ insideClass = true;

this._next();
return this._readString();
return normalizeWhitespace(this._readString());
}
if (ch === '/') {
this._next();
return new RegExp(this._readRegex());
return this._readRegex();
}

@@ -261,15 +390,10 @@ return null;

}
function parseAriaKey(key) {
return KeyParser.parse(key);
}
class AriaKeyError extends Error {
constructor(message, input, pos) {
super(message + ':\n\n' + input + '\n' + ' '.repeat(pos) + '^\n');
this.shortMessage = void 0;
exports.KeyParser = KeyParser;
class ParserError extends Error {
constructor(message, pos) {
super(message);
this.pos = void 0;
this.shortMessage = message;
this.pos = pos;
this.stack = undefined;
}
}
exports.AriaKeyError = AriaKeyError;
exports.ParserError = ParserError;

@@ -49,3 +49,3 @@ "use strict";

} catch (e) {
const newMessage = e.message + ` while parsing selector "${selector}"`;
const newMessage = e.message + ` while parsing css selector "${selector}". Did you mean to CSS.escape it?`;
const index = (e.stack || '').indexOf(e.message);

@@ -65,7 +65,7 @@ if (index !== -1) e.stack = e.stack.substring(0, index) + newMessage + e.stack.substring(index + e.message.length);

});
if (unsupportedToken) throw new InvalidSelectorError(`Unsupported token "${unsupportedToken.toSource()}" while parsing selector "${selector}"`);
if (unsupportedToken) throw new InvalidSelectorError(`Unsupported token "${unsupportedToken.toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`);
let pos = 0;
const names = new Set();
function unexpected() {
return new InvalidSelectorError(`Unexpected token "${tokens[pos].toSource()}" while parsing selector "${selector}"`);
return new InvalidSelectorError(`Unexpected token "${tokens[pos].toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`);
}

@@ -232,3 +232,3 @@ function skipWhitespace() {

if (!isEOF()) throw unexpected();
if (result.some(arg => typeof arg !== 'object' || !('simples' in arg))) throw new InvalidSelectorError(`Error while parsing selector "${selector}"`);
if (result.some(arg => typeof arg !== 'object' || !('simples' in arg))) throw new InvalidSelectorError(`Error while parsing css selector "${selector}". Did you mean to CSS.escape it?`);
return {

@@ -235,0 +235,0 @@ selector: result,

@@ -28,3 +28,3 @@ "use strict";

function asLocator(lang, selector, isFrameLocator = false) {
return asLocators(lang, selector, isFrameLocator)[0];
return asLocators(lang, selector, isFrameLocator, 1)[0];
}

@@ -239,3 +239,3 @@ function asLocators(lang, selector, isFrameLocator = false, maxOutputSize = 20, preferredQuote) {

result.push(factory.chainLocators(currentTokens));
return currentTokens.length < maxOutputSize;
return result.length < maxOutputSize;
}

@@ -242,0 +242,0 @@ for (const taken of tokens[index]) {

@@ -7,2 +7,3 @@ "use strict";

exports.locatorOrSelectorAsSelector = locatorOrSelectorAsSelector;
exports.unsafeLocatorOrSelectorAsSelector = unsafeLocatorOrSelectorAsSelector;
var _stringUtils = require("./stringUtils");

@@ -70,3 +71,3 @@ var _locatorGenerators = require("./locatorGenerators");

.replace(/:/g, '=').replace(/,re\.ignorecase/g, 'i').replace(/,pattern.case_insensitive/g, 'i').replace(/,regexoptions.ignorecase/g, 'i').replace(/re.compile\(([^)]+)\)/g, '$1') // Python has regex strings as r"foo"
.replace(/pattern.compile\(([^)]+)\)/g, 'r$1').replace(/newregex\(([^)]+)\)/g, 'r$1').replace(/string=/g, '=').replace(/regex=/g, '=').replace(/,,/g, ',');
.replace(/pattern.compile\(([^)]+)\)/g, 'r$1').replace(/newregex\(([^)]+)\)/g, 'r$1').replace(/string=/g, '=').replace(/regex=/g, '=').replace(/,,/g, ',').replace(/,\)/g, ')');
const preferredQuote = params.map(p => p.quote).filter(quote => '\'"`'.includes(quote))[0];

@@ -128,3 +129,3 @@ return {

// Transform to selector engines.
template = template.replace(/\,set([\w]+)\(([^)]+)\)/g, (_, group1, group2) => ',' + group1.toLowerCase() + '=' + group2.toLowerCase()).replace(/framelocator\(([^)]+)\)/g, '$1.internal:control=enter-frame').replace(/contentframe(\(\))?/g, 'internal:control=enter-frame').replace(/locator\(([^)]+),hastext=([^),]+)\)/g, 'locator($1).internal:has-text=$2').replace(/locator\(([^)]+),hasnottext=([^),]+)\)/g, 'locator($1).internal:has-not-text=$2').replace(/locator\(([^)]+),hastext=([^),]+)\)/g, 'locator($1).internal:has-text=$2').replace(/locator\(([^)]+)\)/g, '$1').replace(/getbyrole\(([^)]+)\)/g, 'internal:role=$1').replace(/getbytext\(([^)]+)\)/g, 'internal:text=$1').replace(/getbylabel\(([^)]+)\)/g, 'internal:label=$1').replace(/getbytestid\(([^)]+)\)/g, `internal:testid=[${testIdAttributeName}=$1]`).replace(/getby(placeholder|alt|title)(?:text)?\(([^)]+)\)/g, 'internal:attr=[$1=$2]').replace(/first(\(\))?/g, 'nth=0').replace(/last(\(\))?/g, 'nth=-1').replace(/nth\(([^)]+)\)/g, 'nth=$1').replace(/filter\(,?hastext=([^)]+)\)/g, 'internal:has-text=$1').replace(/filter\(,?hasnottext=([^)]+)\)/g, 'internal:has-not-text=$1').replace(/filter\(,?has2=([^)]+)\)/g, 'internal:has=$1').replace(/filter\(,?hasnot2=([^)]+)\)/g, 'internal:has-not=$1').replace(/,exact=false/g, '').replace(/,exact=true/g, 's').replace(/\,/g, '][');
template = template.replace(/\,set([\w]+)\(([^)]+)\)/g, (_, group1, group2) => ',' + group1.toLowerCase() + '=' + group2.toLowerCase()).replace(/framelocator\(([^)]+)\)/g, '$1.internal:control=enter-frame').replace(/contentframe(\(\))?/g, 'internal:control=enter-frame').replace(/locator\(([^)]+),hastext=([^),]+)\)/g, 'locator($1).internal:has-text=$2').replace(/locator\(([^)]+),hasnottext=([^),]+)\)/g, 'locator($1).internal:has-not-text=$2').replace(/locator\(([^)]+),hastext=([^),]+)\)/g, 'locator($1).internal:has-text=$2').replace(/locator\(([^)]+)\)/g, '$1').replace(/getbyrole\(([^)]+)\)/g, 'internal:role=$1').replace(/getbytext\(([^)]+)\)/g, 'internal:text=$1').replace(/getbylabel\(([^)]+)\)/g, 'internal:label=$1').replace(/getbytestid\(([^)]+)\)/g, `internal:testid=[${testIdAttributeName}=$1]`).replace(/getby(placeholder|alt|title)(?:text)?\(([^)]+)\)/g, 'internal:attr=[$1=$2]').replace(/first(\(\))?/g, 'nth=0').replace(/last(\(\))?/g, 'nth=-1').replace(/nth\(([^)]+)\)/g, 'nth=$1').replace(/filter\(,?hastext=([^)]+)\)/g, 'internal:has-text=$1').replace(/filter\(,?hasnottext=([^)]+)\)/g, 'internal:has-not-text=$1').replace(/filter\(,?has2=([^)]+)\)/g, 'internal:has=$1').replace(/filter\(,?hasnot2=([^)]+)\)/g, 'internal:has-not=$1').replace(/,exact=false/g, '').replace(/,exact=true/g, 's').replace(/,includehidden=/g, ',include-hidden=').replace(/\,/g, '][');
const parts = template.split('.');

@@ -164,14 +165,19 @@ // Turn "internal:control=enter-frame >> nth=0" into "nth=0 >> internal:control=enter-frame"

try {
return unsafeLocatorOrSelectorAsSelector(language, locator, testIdAttributeName);
} catch (e) {
return '';
}
}
function unsafeLocatorOrSelectorAsSelector(language, locator, testIdAttributeName) {
try {
(0, _selectorParser.parseSelector)(locator);
return locator;
} catch (e) {}
try {
const {
selector,
preferredQuote
} = parseLocator(locator, testIdAttributeName);
const locators = (0, _locatorGenerators.asLocators)(language, selector, undefined, undefined, preferredQuote);
const digest = digestForComparison(language, locator);
if (locators.some(candidate => digestForComparison(language, candidate) === digest)) return selector;
} catch (e) {}
const {
selector,
preferredQuote
} = parseLocator(locator, testIdAttributeName);
const locators = (0, _locatorGenerators.asLocators)(language, selector, undefined, undefined, preferredQuote);
const digest = digestForComparison(language, locator);
if (locators.some(candidate => digestForComparison(language, candidate) === digest)) return selector;
return '';

@@ -181,4 +187,4 @@ }

locator = locator.replace(/\s/g, '');
if (language === 'javascript') locator = locator.replace(/\\?["`]/g, '\'');
if (language === 'javascript') locator = locator.replace(/\\?["`]/g, '\'').replace(/,{}/g, '');
return locator;
}

@@ -104,10 +104,8 @@ "use strict";

if (isRegExp(match)) return match.test(urlString);
if (typeof match === 'string' && match === urlString) return true;
const url = parsedURL(urlString);
const url = parseURL(urlString);
if (!url) return false;
if (typeof match === 'string') return url.pathname === match;
if (typeof match !== 'function') throw new Error('url parameter should be string, RegExp or function');
return match(url);
}
function parsedURL(url) {
function parseURL(url) {
try {

@@ -114,0 +112,0 @@ return new URL(url);

@@ -152,3 +152,3 @@ "use strict";

const waitForCleanup = new Promise(f => fulfillCleanup = f);
spawnedProcess.once('exit', (exitCode, signal) => {
spawnedProcess.once('close', (exitCode, signal) => {
options.log(`[pid=${spawnedProcess.pid}] <process did exit: exitCode=${exitCode}, signal=${signal}>`);

@@ -155,0 +155,0 @@ processClosed = true;

@@ -29,2 +29,3 @@ "use strict";

const perMessageDeflate = exports.perMessageDeflate = {
serverNoContextTakeover: true,
zlibDeflateOptions: {

@@ -31,0 +32,0 @@ level: 3

@@ -27,27 +27,20 @@ "use strict";

this._asyncLocalStorage = new _async_hooks.AsyncLocalStorage();
this._emptyZone = Zone.createEmpty(this._asyncLocalStorage);
}
run(type, data, func) {
const zone = Zone._createWithData(this._asyncLocalStorage, type, data);
return this._asyncLocalStorage.run(zone, func);
return this.current().with(type, data).run(func);
}
zoneData(type) {
const zone = this._asyncLocalStorage.getStore();
return zone === null || zone === void 0 ? void 0 : zone.get(type);
return this.current().data(type);
}
currentZone() {
current() {
var _this$_asyncLocalStor;
return (_this$_asyncLocalStor = this._asyncLocalStorage.getStore()) !== null && _this$_asyncLocalStor !== void 0 ? _this$_asyncLocalStor : Zone._createEmpty(this._asyncLocalStorage);
return (_this$_asyncLocalStor = this._asyncLocalStorage.getStore()) !== null && _this$_asyncLocalStor !== void 0 ? _this$_asyncLocalStor : this._emptyZone;
}
exitZones(func) {
return this._asyncLocalStorage.run(undefined, func);
empty() {
return this._emptyZone;
}
}
class Zone {
static _createWithData(asyncLocalStorage, type, data) {
var _asyncLocalStorage$ge;
const store = new Map((_asyncLocalStorage$ge = asyncLocalStorage.getStore()) === null || _asyncLocalStorage$ge === void 0 ? void 0 : _asyncLocalStorage$ge._data);
store.set(type, data);
return new Zone(asyncLocalStorage, store);
}
static _createEmpty(asyncLocalStorage) {
static createEmpty(asyncLocalStorage) {
return new Zone(asyncLocalStorage, new Map());

@@ -61,9 +54,14 @@ }

}
with(type, data) {
return new Zone(this._asyncLocalStorage, new Map(this._data).set(type, data));
}
without(type) {
const data = type ? new Map(this._data) : new Map();
data.delete(type);
return new Zone(this._asyncLocalStorage, data);
}
run(func) {
// Reset apiZone and expectZone, but restore stepZone.
const entries = [...this._data.entries()].filter(([type]) => type !== 'apiZone' && type !== 'expectZone');
const resetZone = new Zone(this._asyncLocalStorage, new Map(entries));
return this._asyncLocalStorage.run(resetZone, func);
return this._asyncLocalStorage.run(this, func);
}
get(type) {
data(type) {
return this._data.get(type);

@@ -70,0 +68,0 @@ }

{
"name": "playwright-core",
"version": "1.50.0-beta-1731498714000",
"version": "1.50.0-beta-1737137869000",
"description": "A high-level API to automate web browsers",

@@ -5,0 +5,0 @@ "repository": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc