409 lines
19 KiB
JavaScript
409 lines
19 KiB
JavaScript
"use strict";
|
|
var __create = Object.create;
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __getProtoOf = Object.getPrototypeOf;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
// file that has been converted to a CommonJS file using a Babel-
|
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
mod
|
|
));
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var frame_exports = {};
|
|
__export(frame_exports, {
|
|
Frame: () => Frame,
|
|
verifyLoadState: () => verifyLoadState
|
|
});
|
|
module.exports = __toCommonJS(frame_exports);
|
|
var import_eventEmitter = require("./eventEmitter");
|
|
var import_channelOwner = require("./channelOwner");
|
|
var import_clientHelper = require("./clientHelper");
|
|
var import_elementHandle = require("./elementHandle");
|
|
var import_events = require("./events");
|
|
var import_jsHandle = require("./jsHandle");
|
|
var import_locator = require("./locator");
|
|
var network = __toESM(require("./network"));
|
|
var import_types = require("./types");
|
|
var import_waiter = require("./waiter");
|
|
var import_assert = require("../utils/isomorphic/assert");
|
|
var import_locatorUtils = require("../utils/isomorphic/locatorUtils");
|
|
var import_urlMatch = require("../utils/isomorphic/urlMatch");
|
|
var import_timeoutSettings = require("./timeoutSettings");
|
|
class Frame extends import_channelOwner.ChannelOwner {
|
|
constructor(parent, type, guid, initializer) {
|
|
super(parent, type, guid, initializer);
|
|
this._parentFrame = null;
|
|
this._url = "";
|
|
this._name = "";
|
|
this._detached = false;
|
|
this._childFrames = /* @__PURE__ */ new Set();
|
|
this._eventEmitter = new import_eventEmitter.EventEmitter(parent._platform);
|
|
this._eventEmitter.setMaxListeners(0);
|
|
this._parentFrame = Frame.fromNullable(initializer.parentFrame);
|
|
if (this._parentFrame)
|
|
this._parentFrame._childFrames.add(this);
|
|
this._name = initializer.name;
|
|
this._url = initializer.url;
|
|
this._loadStates = new Set(initializer.loadStates);
|
|
this._channel.on("loadstate", (event) => {
|
|
if (event.add) {
|
|
this._loadStates.add(event.add);
|
|
this._eventEmitter.emit("loadstate", event.add);
|
|
}
|
|
if (event.remove)
|
|
this._loadStates.delete(event.remove);
|
|
if (!this._parentFrame && event.add === "load" && this._page)
|
|
this._page.emit(import_events.Events.Page.Load, this._page);
|
|
if (!this._parentFrame && event.add === "domcontentloaded" && this._page)
|
|
this._page.emit(import_events.Events.Page.DOMContentLoaded, this._page);
|
|
});
|
|
this._channel.on("navigated", (event) => {
|
|
this._url = event.url;
|
|
this._name = event.name;
|
|
this._eventEmitter.emit("navigated", event);
|
|
if (!event.error && this._page)
|
|
this._page.emit(import_events.Events.Page.FrameNavigated, this);
|
|
});
|
|
}
|
|
static from(frame) {
|
|
return frame._object;
|
|
}
|
|
static fromNullable(frame) {
|
|
return frame ? Frame.from(frame) : null;
|
|
}
|
|
page() {
|
|
return this._page;
|
|
}
|
|
_timeout(options) {
|
|
const timeoutSettings = this._page?._timeoutSettings || new import_timeoutSettings.TimeoutSettings(this._platform);
|
|
return timeoutSettings.timeout(options || {});
|
|
}
|
|
_navigationTimeout(options) {
|
|
const timeoutSettings = this._page?._timeoutSettings || new import_timeoutSettings.TimeoutSettings(this._platform);
|
|
return timeoutSettings.navigationTimeout(options || {});
|
|
}
|
|
async goto(url, options = {}) {
|
|
const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
|
|
return network.Response.fromNullable((await this._channel.goto({ url, ...options, waitUntil, timeout: this._navigationTimeout(options) })).response);
|
|
}
|
|
_setupNavigationWaiter(options) {
|
|
const waiter = new import_waiter.Waiter(this._page, "");
|
|
if (this._page.isClosed())
|
|
waiter.rejectImmediately(this._page._closeErrorWithReason());
|
|
waiter.rejectOnEvent(this._page, import_events.Events.Page.Close, () => this._page._closeErrorWithReason());
|
|
waiter.rejectOnEvent(this._page, import_events.Events.Page.Crash, new Error("Navigation failed because page crashed!"));
|
|
waiter.rejectOnEvent(this._page, import_events.Events.Page.FrameDetached, new Error("Navigating frame was detached!"), (frame) => frame === this);
|
|
const timeout = this._page._timeoutSettings.navigationTimeout(options);
|
|
waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded.`);
|
|
return waiter;
|
|
}
|
|
async waitForNavigation(options = {}) {
|
|
return await this._page._wrapApiCall(async () => {
|
|
const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
|
|
const waiter = this._setupNavigationWaiter(options);
|
|
const toUrl = typeof options.url === "string" ? ` to "${options.url}"` : "";
|
|
waiter.log(`waiting for navigation${toUrl} until "${waitUntil}"`);
|
|
const navigatedEvent = await waiter.waitForEvent(this._eventEmitter, "navigated", (event) => {
|
|
if (event.error)
|
|
return true;
|
|
waiter.log(` navigated to "${event.url}"`);
|
|
return (0, import_urlMatch.urlMatches)(this._page?.context()._options.baseURL, event.url, options.url);
|
|
});
|
|
if (navigatedEvent.error) {
|
|
const e = new Error(navigatedEvent.error);
|
|
e.stack = "";
|
|
await waiter.waitForPromise(Promise.reject(e));
|
|
}
|
|
if (!this._loadStates.has(waitUntil)) {
|
|
await waiter.waitForEvent(this._eventEmitter, "loadstate", (s) => {
|
|
waiter.log(` "${s}" event fired`);
|
|
return s === waitUntil;
|
|
});
|
|
}
|
|
const request = navigatedEvent.newDocument ? network.Request.fromNullable(navigatedEvent.newDocument.request) : null;
|
|
const response = request ? await waiter.waitForPromise(request._finalRequest()._internalResponse()) : null;
|
|
waiter.dispose();
|
|
return response;
|
|
}, { title: "Wait for navigation" });
|
|
}
|
|
async waitForLoadState(state = "load", options = {}) {
|
|
state = verifyLoadState("state", state);
|
|
return await this._page._wrapApiCall(async () => {
|
|
const waiter = this._setupNavigationWaiter(options);
|
|
if (this._loadStates.has(state)) {
|
|
waiter.log(` not waiting, "${state}" event already fired`);
|
|
} else {
|
|
await waiter.waitForEvent(this._eventEmitter, "loadstate", (s) => {
|
|
waiter.log(` "${s}" event fired`);
|
|
return s === state;
|
|
});
|
|
}
|
|
waiter.dispose();
|
|
}, { title: `Wait for load state "${state}"` });
|
|
}
|
|
async waitForURL(url, options = {}) {
|
|
if ((0, import_urlMatch.urlMatches)(this._page?.context()._options.baseURL, this.url(), url))
|
|
return await this.waitForLoadState(options.waitUntil, options);
|
|
await this.waitForNavigation({ url, ...options });
|
|
}
|
|
async frameElement() {
|
|
return import_elementHandle.ElementHandle.from((await this._channel.frameElement()).element);
|
|
}
|
|
async evaluateHandle(pageFunction, arg) {
|
|
(0, import_jsHandle.assertMaxArguments)(arguments.length, 2);
|
|
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
|
return import_jsHandle.JSHandle.from(result.handle);
|
|
}
|
|
async evaluate(pageFunction, arg) {
|
|
(0, import_jsHandle.assertMaxArguments)(arguments.length, 2);
|
|
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
|
return (0, import_jsHandle.parseResult)(result.value);
|
|
}
|
|
async _evaluateFunction(functionDeclaration) {
|
|
const result = await this._channel.evaluateExpression({ expression: functionDeclaration, isFunction: true, arg: (0, import_jsHandle.serializeArgument)(void 0) });
|
|
return (0, import_jsHandle.parseResult)(result.value);
|
|
}
|
|
async _evaluateExposeUtilityScript(pageFunction, arg) {
|
|
(0, import_jsHandle.assertMaxArguments)(arguments.length, 2);
|
|
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
|
return (0, import_jsHandle.parseResult)(result.value);
|
|
}
|
|
async $(selector, options) {
|
|
const result = await this._channel.querySelector({ selector, ...options });
|
|
return import_elementHandle.ElementHandle.fromNullable(result.element);
|
|
}
|
|
async waitForSelector(selector, options = {}) {
|
|
if (options.visibility)
|
|
throw new Error("options.visibility is not supported, did you mean options.state?");
|
|
if (options.waitFor && options.waitFor !== "visible")
|
|
throw new Error("options.waitFor is not supported, did you mean options.state?");
|
|
const result = await this._channel.waitForSelector({ selector, ...options, timeout: this._timeout(options) });
|
|
return import_elementHandle.ElementHandle.fromNullable(result.element);
|
|
}
|
|
async dispatchEvent(selector, type, eventInit, options = {}) {
|
|
await this._channel.dispatchEvent({ selector, type, eventInit: (0, import_jsHandle.serializeArgument)(eventInit), ...options, timeout: this._timeout(options) });
|
|
}
|
|
async $eval(selector, pageFunction, arg) {
|
|
(0, import_jsHandle.assertMaxArguments)(arguments.length, 3);
|
|
const result = await this._channel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
|
return (0, import_jsHandle.parseResult)(result.value);
|
|
}
|
|
async $$eval(selector, pageFunction, arg) {
|
|
(0, import_jsHandle.assertMaxArguments)(arguments.length, 3);
|
|
const result = await this._channel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
|
|
return (0, import_jsHandle.parseResult)(result.value);
|
|
}
|
|
async $$(selector) {
|
|
const result = await this._channel.querySelectorAll({ selector });
|
|
return result.elements.map((e) => import_elementHandle.ElementHandle.from(e));
|
|
}
|
|
async _queryCount(selector, options) {
|
|
return (await this._channel.queryCount({ selector, ...options })).value;
|
|
}
|
|
async content() {
|
|
return (await this._channel.content()).value;
|
|
}
|
|
async setContent(html, options = {}) {
|
|
const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
|
|
await this._channel.setContent({ html, ...options, waitUntil, timeout: this._navigationTimeout(options) });
|
|
}
|
|
name() {
|
|
return this._name || "";
|
|
}
|
|
url() {
|
|
return this._url;
|
|
}
|
|
parentFrame() {
|
|
return this._parentFrame;
|
|
}
|
|
childFrames() {
|
|
return Array.from(this._childFrames);
|
|
}
|
|
isDetached() {
|
|
return this._detached;
|
|
}
|
|
async addScriptTag(options = {}) {
|
|
const copy = { ...options };
|
|
if (copy.path) {
|
|
copy.content = (await this._platform.fs().promises.readFile(copy.path)).toString();
|
|
copy.content = (0, import_clientHelper.addSourceUrlToScript)(copy.content, copy.path);
|
|
}
|
|
return import_elementHandle.ElementHandle.from((await this._channel.addScriptTag({ ...copy })).element);
|
|
}
|
|
async addStyleTag(options = {}) {
|
|
const copy = { ...options };
|
|
if (copy.path) {
|
|
copy.content = (await this._platform.fs().promises.readFile(copy.path)).toString();
|
|
copy.content += "/*# sourceURL=" + copy.path.replace(/\n/g, "") + "*/";
|
|
}
|
|
return import_elementHandle.ElementHandle.from((await this._channel.addStyleTag({ ...copy })).element);
|
|
}
|
|
async click(selector, options = {}) {
|
|
return await this._channel.click({ selector, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async dblclick(selector, options = {}) {
|
|
return await this._channel.dblclick({ selector, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async dragAndDrop(source, target, options = {}) {
|
|
return await this._channel.dragAndDrop({ source, target, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async tap(selector, options = {}) {
|
|
return await this._channel.tap({ selector, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async fill(selector, value, options = {}) {
|
|
return await this._channel.fill({ selector, value, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async _highlight(selector) {
|
|
return await this._channel.highlight({ selector });
|
|
}
|
|
locator(selector, options) {
|
|
return new import_locator.Locator(this, selector, options);
|
|
}
|
|
getByTestId(testId) {
|
|
return this.locator((0, import_locatorUtils.getByTestIdSelector)((0, import_locator.testIdAttributeName)(), testId));
|
|
}
|
|
getByAltText(text, options) {
|
|
return this.locator((0, import_locatorUtils.getByAltTextSelector)(text, options));
|
|
}
|
|
getByLabel(text, options) {
|
|
return this.locator((0, import_locatorUtils.getByLabelSelector)(text, options));
|
|
}
|
|
getByPlaceholder(text, options) {
|
|
return this.locator((0, import_locatorUtils.getByPlaceholderSelector)(text, options));
|
|
}
|
|
getByText(text, options) {
|
|
return this.locator((0, import_locatorUtils.getByTextSelector)(text, options));
|
|
}
|
|
getByTitle(text, options) {
|
|
return this.locator((0, import_locatorUtils.getByTitleSelector)(text, options));
|
|
}
|
|
getByRole(role, options = {}) {
|
|
return this.locator((0, import_locatorUtils.getByRoleSelector)(role, options));
|
|
}
|
|
frameLocator(selector) {
|
|
return new import_locator.FrameLocator(this, selector);
|
|
}
|
|
async focus(selector, options = {}) {
|
|
await this._channel.focus({ selector, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async textContent(selector, options = {}) {
|
|
const value = (await this._channel.textContent({ selector, ...options, timeout: this._timeout(options) })).value;
|
|
return value === void 0 ? null : value;
|
|
}
|
|
async innerText(selector, options = {}) {
|
|
return (await this._channel.innerText({ selector, ...options, timeout: this._timeout(options) })).value;
|
|
}
|
|
async innerHTML(selector, options = {}) {
|
|
return (await this._channel.innerHTML({ selector, ...options, timeout: this._timeout(options) })).value;
|
|
}
|
|
async getAttribute(selector, name, options = {}) {
|
|
const value = (await this._channel.getAttribute({ selector, name, ...options, timeout: this._timeout(options) })).value;
|
|
return value === void 0 ? null : value;
|
|
}
|
|
async inputValue(selector, options = {}) {
|
|
return (await this._channel.inputValue({ selector, ...options, timeout: this._timeout(options) })).value;
|
|
}
|
|
async isChecked(selector, options = {}) {
|
|
return (await this._channel.isChecked({ selector, ...options, timeout: this._timeout(options) })).value;
|
|
}
|
|
async isDisabled(selector, options = {}) {
|
|
return (await this._channel.isDisabled({ selector, ...options, timeout: this._timeout(options) })).value;
|
|
}
|
|
async isEditable(selector, options = {}) {
|
|
return (await this._channel.isEditable({ selector, ...options, timeout: this._timeout(options) })).value;
|
|
}
|
|
async isEnabled(selector, options = {}) {
|
|
return (await this._channel.isEnabled({ selector, ...options, timeout: this._timeout(options) })).value;
|
|
}
|
|
async isHidden(selector, options = {}) {
|
|
return (await this._channel.isHidden({ selector, ...options })).value;
|
|
}
|
|
async isVisible(selector, options = {}) {
|
|
return (await this._channel.isVisible({ selector, ...options })).value;
|
|
}
|
|
async hover(selector, options = {}) {
|
|
await this._channel.hover({ selector, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async selectOption(selector, values, options = {}) {
|
|
return (await this._channel.selectOption({ selector, ...(0, import_elementHandle.convertSelectOptionValues)(values), ...options, timeout: this._timeout(options) })).values;
|
|
}
|
|
async setInputFiles(selector, files, options = {}) {
|
|
const converted = await (0, import_elementHandle.convertInputFiles)(this._platform, files, this.page().context());
|
|
await this._channel.setInputFiles({ selector, ...converted, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async type(selector, text, options = {}) {
|
|
await this._channel.type({ selector, text, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async press(selector, key, options = {}) {
|
|
await this._channel.press({ selector, key, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async check(selector, options = {}) {
|
|
await this._channel.check({ selector, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async uncheck(selector, options = {}) {
|
|
await this._channel.uncheck({ selector, ...options, timeout: this._timeout(options) });
|
|
}
|
|
async setChecked(selector, checked, options) {
|
|
if (checked)
|
|
await this.check(selector, options);
|
|
else
|
|
await this.uncheck(selector, options);
|
|
}
|
|
async waitForTimeout(timeout) {
|
|
await this._channel.waitForTimeout({ waitTimeout: timeout });
|
|
}
|
|
async waitForFunction(pageFunction, arg, options = {}) {
|
|
if (typeof options.polling === "string")
|
|
(0, import_assert.assert)(options.polling === "raf", "Unknown polling option: " + options.polling);
|
|
const result = await this._channel.waitForFunction({
|
|
...options,
|
|
pollingInterval: options.polling === "raf" ? void 0 : options.polling,
|
|
expression: String(pageFunction),
|
|
isFunction: typeof pageFunction === "function",
|
|
arg: (0, import_jsHandle.serializeArgument)(arg),
|
|
timeout: this._timeout(options)
|
|
});
|
|
return import_jsHandle.JSHandle.from(result.handle);
|
|
}
|
|
async title() {
|
|
return (await this._channel.title()).value;
|
|
}
|
|
async _expect(expression, options) {
|
|
const params = { expression, ...options, isNot: !!options.isNot };
|
|
params.expectedValue = (0, import_jsHandle.serializeArgument)(options.expectedValue);
|
|
const result = await this._channel.expect(params);
|
|
if (result.received !== void 0)
|
|
result.received = (0, import_jsHandle.parseResult)(result.received);
|
|
return result;
|
|
}
|
|
}
|
|
function verifyLoadState(name, waitUntil) {
|
|
if (waitUntil === "networkidle0")
|
|
waitUntil = "networkidle";
|
|
if (!import_types.kLifecycleEvents.has(waitUntil))
|
|
throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle|commit)`);
|
|
return waitUntil;
|
|
}
|
|
// Annotate the CommonJS export names for ESM import in node:
|
|
0 && (module.exports = {
|
|
Frame,
|
|
verifyLoadState
|
|
});
|