frame.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. "use strict";
  2. var __create = Object.create;
  3. var __defProp = Object.defineProperty;
  4. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  5. var __getOwnPropNames = Object.getOwnPropertyNames;
  6. var __getProtoOf = Object.getPrototypeOf;
  7. var __hasOwnProp = Object.prototype.hasOwnProperty;
  8. var __export = (target, all) => {
  9. for (var name in all)
  10. __defProp(target, name, { get: all[name], enumerable: true });
  11. };
  12. var __copyProps = (to, from, except, desc) => {
  13. if (from && typeof from === "object" || typeof from === "function") {
  14. for (let key of __getOwnPropNames(from))
  15. if (!__hasOwnProp.call(to, key) && key !== except)
  16. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  17. }
  18. return to;
  19. };
  20. var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  21. // If the importer is in node compatibility mode or this is not an ESM
  22. // file that has been converted to a CommonJS file using a Babel-
  23. // compatible transform (i.e. "__esModule" has not been set), then set
  24. // "default" to the CommonJS "module.exports" for node compatibility.
  25. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  26. mod
  27. ));
  28. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  29. var frame_exports = {};
  30. __export(frame_exports, {
  31. Frame: () => Frame,
  32. verifyLoadState: () => verifyLoadState
  33. });
  34. module.exports = __toCommonJS(frame_exports);
  35. var import_eventEmitter = require("./eventEmitter");
  36. var import_channelOwner = require("./channelOwner");
  37. var import_clientHelper = require("./clientHelper");
  38. var import_elementHandle = require("./elementHandle");
  39. var import_events = require("./events");
  40. var import_jsHandle = require("./jsHandle");
  41. var import_locator = require("./locator");
  42. var network = __toESM(require("./network"));
  43. var import_types = require("./types");
  44. var import_waiter = require("./waiter");
  45. var import_assert = require("../utils/isomorphic/assert");
  46. var import_locatorUtils = require("../utils/isomorphic/locatorUtils");
  47. var import_urlMatch = require("../utils/isomorphic/urlMatch");
  48. var import_timeoutSettings = require("./timeoutSettings");
  49. class Frame extends import_channelOwner.ChannelOwner {
  50. constructor(parent, type, guid, initializer) {
  51. super(parent, type, guid, initializer);
  52. this._parentFrame = null;
  53. this._url = "";
  54. this._name = "";
  55. this._detached = false;
  56. this._childFrames = /* @__PURE__ */ new Set();
  57. this._eventEmitter = new import_eventEmitter.EventEmitter(parent._platform);
  58. this._eventEmitter.setMaxListeners(0);
  59. this._parentFrame = Frame.fromNullable(initializer.parentFrame);
  60. if (this._parentFrame)
  61. this._parentFrame._childFrames.add(this);
  62. this._name = initializer.name;
  63. this._url = initializer.url;
  64. this._loadStates = new Set(initializer.loadStates);
  65. this._channel.on("loadstate", (event) => {
  66. if (event.add) {
  67. this._loadStates.add(event.add);
  68. this._eventEmitter.emit("loadstate", event.add);
  69. }
  70. if (event.remove)
  71. this._loadStates.delete(event.remove);
  72. if (!this._parentFrame && event.add === "load" && this._page)
  73. this._page.emit(import_events.Events.Page.Load, this._page);
  74. if (!this._parentFrame && event.add === "domcontentloaded" && this._page)
  75. this._page.emit(import_events.Events.Page.DOMContentLoaded, this._page);
  76. });
  77. this._channel.on("navigated", (event) => {
  78. this._url = event.url;
  79. this._name = event.name;
  80. this._eventEmitter.emit("navigated", event);
  81. if (!event.error && this._page)
  82. this._page.emit(import_events.Events.Page.FrameNavigated, this);
  83. });
  84. }
  85. static from(frame) {
  86. return frame._object;
  87. }
  88. static fromNullable(frame) {
  89. return frame ? Frame.from(frame) : null;
  90. }
  91. page() {
  92. return this._page;
  93. }
  94. _timeout(options) {
  95. const timeoutSettings = this._page?._timeoutSettings || new import_timeoutSettings.TimeoutSettings(this._platform);
  96. return timeoutSettings.timeout(options || {});
  97. }
  98. _navigationTimeout(options) {
  99. const timeoutSettings = this._page?._timeoutSettings || new import_timeoutSettings.TimeoutSettings(this._platform);
  100. return timeoutSettings.navigationTimeout(options || {});
  101. }
  102. async goto(url, options = {}) {
  103. const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
  104. return network.Response.fromNullable((await this._channel.goto({ url, ...options, waitUntil, timeout: this._navigationTimeout(options) })).response);
  105. }
  106. _setupNavigationWaiter(options) {
  107. const waiter = new import_waiter.Waiter(this._page, "");
  108. if (this._page.isClosed())
  109. waiter.rejectImmediately(this._page._closeErrorWithReason());
  110. waiter.rejectOnEvent(this._page, import_events.Events.Page.Close, () => this._page._closeErrorWithReason());
  111. waiter.rejectOnEvent(this._page, import_events.Events.Page.Crash, new Error("Navigation failed because page crashed!"));
  112. waiter.rejectOnEvent(this._page, import_events.Events.Page.FrameDetached, new Error("Navigating frame was detached!"), (frame) => frame === this);
  113. const timeout = this._page._timeoutSettings.navigationTimeout(options);
  114. waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded.`);
  115. return waiter;
  116. }
  117. async waitForNavigation(options = {}) {
  118. return await this._page._wrapApiCall(async () => {
  119. const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
  120. const waiter = this._setupNavigationWaiter(options);
  121. const toUrl = typeof options.url === "string" ? ` to "${options.url}"` : "";
  122. waiter.log(`waiting for navigation${toUrl} until "${waitUntil}"`);
  123. const navigatedEvent = await waiter.waitForEvent(this._eventEmitter, "navigated", (event) => {
  124. if (event.error)
  125. return true;
  126. waiter.log(` navigated to "${event.url}"`);
  127. return (0, import_urlMatch.urlMatches)(this._page?.context()._options.baseURL, event.url, options.url);
  128. });
  129. if (navigatedEvent.error) {
  130. const e = new Error(navigatedEvent.error);
  131. e.stack = "";
  132. await waiter.waitForPromise(Promise.reject(e));
  133. }
  134. if (!this._loadStates.has(waitUntil)) {
  135. await waiter.waitForEvent(this._eventEmitter, "loadstate", (s) => {
  136. waiter.log(` "${s}" event fired`);
  137. return s === waitUntil;
  138. });
  139. }
  140. const request = navigatedEvent.newDocument ? network.Request.fromNullable(navigatedEvent.newDocument.request) : null;
  141. const response = request ? await waiter.waitForPromise(request._finalRequest()._internalResponse()) : null;
  142. waiter.dispose();
  143. return response;
  144. }, { title: "Wait for navigation" });
  145. }
  146. async waitForLoadState(state = "load", options = {}) {
  147. state = verifyLoadState("state", state);
  148. return await this._page._wrapApiCall(async () => {
  149. const waiter = this._setupNavigationWaiter(options);
  150. if (this._loadStates.has(state)) {
  151. waiter.log(` not waiting, "${state}" event already fired`);
  152. } else {
  153. await waiter.waitForEvent(this._eventEmitter, "loadstate", (s) => {
  154. waiter.log(` "${s}" event fired`);
  155. return s === state;
  156. });
  157. }
  158. waiter.dispose();
  159. }, { title: `Wait for load state "${state}"` });
  160. }
  161. async waitForURL(url, options = {}) {
  162. if ((0, import_urlMatch.urlMatches)(this._page?.context()._options.baseURL, this.url(), url))
  163. return await this.waitForLoadState(options.waitUntil, options);
  164. await this.waitForNavigation({ url, ...options });
  165. }
  166. async frameElement() {
  167. return import_elementHandle.ElementHandle.from((await this._channel.frameElement()).element);
  168. }
  169. async evaluateHandle(pageFunction, arg) {
  170. (0, import_jsHandle.assertMaxArguments)(arguments.length, 2);
  171. const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
  172. return import_jsHandle.JSHandle.from(result.handle);
  173. }
  174. async evaluate(pageFunction, arg) {
  175. (0, import_jsHandle.assertMaxArguments)(arguments.length, 2);
  176. const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
  177. return (0, import_jsHandle.parseResult)(result.value);
  178. }
  179. async _evaluateFunction(functionDeclaration) {
  180. const result = await this._channel.evaluateExpression({ expression: functionDeclaration, isFunction: true, arg: (0, import_jsHandle.serializeArgument)(void 0) });
  181. return (0, import_jsHandle.parseResult)(result.value);
  182. }
  183. async _evaluateExposeUtilityScript(pageFunction, arg) {
  184. (0, import_jsHandle.assertMaxArguments)(arguments.length, 2);
  185. const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
  186. return (0, import_jsHandle.parseResult)(result.value);
  187. }
  188. async $(selector, options) {
  189. const result = await this._channel.querySelector({ selector, ...options });
  190. return import_elementHandle.ElementHandle.fromNullable(result.element);
  191. }
  192. async waitForSelector(selector, options = {}) {
  193. if (options.visibility)
  194. throw new Error("options.visibility is not supported, did you mean options.state?");
  195. if (options.waitFor && options.waitFor !== "visible")
  196. throw new Error("options.waitFor is not supported, did you mean options.state?");
  197. const result = await this._channel.waitForSelector({ selector, ...options, timeout: this._timeout(options) });
  198. return import_elementHandle.ElementHandle.fromNullable(result.element);
  199. }
  200. async dispatchEvent(selector, type, eventInit, options = {}) {
  201. await this._channel.dispatchEvent({ selector, type, eventInit: (0, import_jsHandle.serializeArgument)(eventInit), ...options, timeout: this._timeout(options) });
  202. }
  203. async $eval(selector, pageFunction, arg) {
  204. (0, import_jsHandle.assertMaxArguments)(arguments.length, 3);
  205. const result = await this._channel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
  206. return (0, import_jsHandle.parseResult)(result.value);
  207. }
  208. async $$eval(selector, pageFunction, arg) {
  209. (0, import_jsHandle.assertMaxArguments)(arguments.length, 3);
  210. const result = await this._channel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === "function", arg: (0, import_jsHandle.serializeArgument)(arg) });
  211. return (0, import_jsHandle.parseResult)(result.value);
  212. }
  213. async $$(selector) {
  214. const result = await this._channel.querySelectorAll({ selector });
  215. return result.elements.map((e) => import_elementHandle.ElementHandle.from(e));
  216. }
  217. async _queryCount(selector, options) {
  218. return (await this._channel.queryCount({ selector, ...options })).value;
  219. }
  220. async content() {
  221. return (await this._channel.content()).value;
  222. }
  223. async setContent(html, options = {}) {
  224. const waitUntil = verifyLoadState("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil);
  225. await this._channel.setContent({ html, ...options, waitUntil, timeout: this._navigationTimeout(options) });
  226. }
  227. name() {
  228. return this._name || "";
  229. }
  230. url() {
  231. return this._url;
  232. }
  233. parentFrame() {
  234. return this._parentFrame;
  235. }
  236. childFrames() {
  237. return Array.from(this._childFrames);
  238. }
  239. isDetached() {
  240. return this._detached;
  241. }
  242. async addScriptTag(options = {}) {
  243. const copy = { ...options };
  244. if (copy.path) {
  245. copy.content = (await this._platform.fs().promises.readFile(copy.path)).toString();
  246. copy.content = (0, import_clientHelper.addSourceUrlToScript)(copy.content, copy.path);
  247. }
  248. return import_elementHandle.ElementHandle.from((await this._channel.addScriptTag({ ...copy })).element);
  249. }
  250. async addStyleTag(options = {}) {
  251. const copy = { ...options };
  252. if (copy.path) {
  253. copy.content = (await this._platform.fs().promises.readFile(copy.path)).toString();
  254. copy.content += "/*# sourceURL=" + copy.path.replace(/\n/g, "") + "*/";
  255. }
  256. return import_elementHandle.ElementHandle.from((await this._channel.addStyleTag({ ...copy })).element);
  257. }
  258. async click(selector, options = {}) {
  259. return await this._channel.click({ selector, ...options, timeout: this._timeout(options) });
  260. }
  261. async dblclick(selector, options = {}) {
  262. return await this._channel.dblclick({ selector, ...options, timeout: this._timeout(options) });
  263. }
  264. async dragAndDrop(source, target, options = {}) {
  265. return await this._channel.dragAndDrop({ source, target, ...options, timeout: this._timeout(options) });
  266. }
  267. async tap(selector, options = {}) {
  268. return await this._channel.tap({ selector, ...options, timeout: this._timeout(options) });
  269. }
  270. async fill(selector, value, options = {}) {
  271. return await this._channel.fill({ selector, value, ...options, timeout: this._timeout(options) });
  272. }
  273. async _highlight(selector) {
  274. return await this._channel.highlight({ selector });
  275. }
  276. locator(selector, options) {
  277. return new import_locator.Locator(this, selector, options);
  278. }
  279. getByTestId(testId) {
  280. return this.locator((0, import_locatorUtils.getByTestIdSelector)((0, import_locator.testIdAttributeName)(), testId));
  281. }
  282. getByAltText(text, options) {
  283. return this.locator((0, import_locatorUtils.getByAltTextSelector)(text, options));
  284. }
  285. getByLabel(text, options) {
  286. return this.locator((0, import_locatorUtils.getByLabelSelector)(text, options));
  287. }
  288. getByPlaceholder(text, options) {
  289. return this.locator((0, import_locatorUtils.getByPlaceholderSelector)(text, options));
  290. }
  291. getByText(text, options) {
  292. return this.locator((0, import_locatorUtils.getByTextSelector)(text, options));
  293. }
  294. getByTitle(text, options) {
  295. return this.locator((0, import_locatorUtils.getByTitleSelector)(text, options));
  296. }
  297. getByRole(role, options = {}) {
  298. return this.locator((0, import_locatorUtils.getByRoleSelector)(role, options));
  299. }
  300. frameLocator(selector) {
  301. return new import_locator.FrameLocator(this, selector);
  302. }
  303. async focus(selector, options = {}) {
  304. await this._channel.focus({ selector, ...options, timeout: this._timeout(options) });
  305. }
  306. async textContent(selector, options = {}) {
  307. const value = (await this._channel.textContent({ selector, ...options, timeout: this._timeout(options) })).value;
  308. return value === void 0 ? null : value;
  309. }
  310. async innerText(selector, options = {}) {
  311. return (await this._channel.innerText({ selector, ...options, timeout: this._timeout(options) })).value;
  312. }
  313. async innerHTML(selector, options = {}) {
  314. return (await this._channel.innerHTML({ selector, ...options, timeout: this._timeout(options) })).value;
  315. }
  316. async getAttribute(selector, name, options = {}) {
  317. const value = (await this._channel.getAttribute({ selector, name, ...options, timeout: this._timeout(options) })).value;
  318. return value === void 0 ? null : value;
  319. }
  320. async inputValue(selector, options = {}) {
  321. return (await this._channel.inputValue({ selector, ...options, timeout: this._timeout(options) })).value;
  322. }
  323. async isChecked(selector, options = {}) {
  324. return (await this._channel.isChecked({ selector, ...options, timeout: this._timeout(options) })).value;
  325. }
  326. async isDisabled(selector, options = {}) {
  327. return (await this._channel.isDisabled({ selector, ...options, timeout: this._timeout(options) })).value;
  328. }
  329. async isEditable(selector, options = {}) {
  330. return (await this._channel.isEditable({ selector, ...options, timeout: this._timeout(options) })).value;
  331. }
  332. async isEnabled(selector, options = {}) {
  333. return (await this._channel.isEnabled({ selector, ...options, timeout: this._timeout(options) })).value;
  334. }
  335. async isHidden(selector, options = {}) {
  336. return (await this._channel.isHidden({ selector, ...options })).value;
  337. }
  338. async isVisible(selector, options = {}) {
  339. return (await this._channel.isVisible({ selector, ...options })).value;
  340. }
  341. async hover(selector, options = {}) {
  342. await this._channel.hover({ selector, ...options, timeout: this._timeout(options) });
  343. }
  344. async selectOption(selector, values, options = {}) {
  345. return (await this._channel.selectOption({ selector, ...(0, import_elementHandle.convertSelectOptionValues)(values), ...options, timeout: this._timeout(options) })).values;
  346. }
  347. async setInputFiles(selector, files, options = {}) {
  348. const converted = await (0, import_elementHandle.convertInputFiles)(this._platform, files, this.page().context());
  349. await this._channel.setInputFiles({ selector, ...converted, ...options, timeout: this._timeout(options) });
  350. }
  351. async type(selector, text, options = {}) {
  352. await this._channel.type({ selector, text, ...options, timeout: this._timeout(options) });
  353. }
  354. async press(selector, key, options = {}) {
  355. await this._channel.press({ selector, key, ...options, timeout: this._timeout(options) });
  356. }
  357. async check(selector, options = {}) {
  358. await this._channel.check({ selector, ...options, timeout: this._timeout(options) });
  359. }
  360. async uncheck(selector, options = {}) {
  361. await this._channel.uncheck({ selector, ...options, timeout: this._timeout(options) });
  362. }
  363. async setChecked(selector, checked, options) {
  364. if (checked)
  365. await this.check(selector, options);
  366. else
  367. await this.uncheck(selector, options);
  368. }
  369. async waitForTimeout(timeout) {
  370. await this._channel.waitForTimeout({ waitTimeout: timeout });
  371. }
  372. async waitForFunction(pageFunction, arg, options = {}) {
  373. if (typeof options.polling === "string")
  374. (0, import_assert.assert)(options.polling === "raf", "Unknown polling option: " + options.polling);
  375. const result = await this._channel.waitForFunction({
  376. ...options,
  377. pollingInterval: options.polling === "raf" ? void 0 : options.polling,
  378. expression: String(pageFunction),
  379. isFunction: typeof pageFunction === "function",
  380. arg: (0, import_jsHandle.serializeArgument)(arg),
  381. timeout: this._timeout(options)
  382. });
  383. return import_jsHandle.JSHandle.from(result.handle);
  384. }
  385. async title() {
  386. return (await this._channel.title()).value;
  387. }
  388. async _expect(expression, options) {
  389. const params = { expression, ...options, isNot: !!options.isNot };
  390. params.expectedValue = (0, import_jsHandle.serializeArgument)(options.expectedValue);
  391. const result = await this._channel.expect(params);
  392. if (result.received !== void 0)
  393. result.received = (0, import_jsHandle.parseResult)(result.received);
  394. return result;
  395. }
  396. }
  397. function verifyLoadState(name, waitUntil) {
  398. if (waitUntil === "networkidle0")
  399. waitUntil = "networkidle";
  400. if (!import_types.kLifecycleEvents.has(waitUntil))
  401. throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle|commit)`);
  402. return waitUntil;
  403. }
  404. // Annotate the CommonJS export names for ESM import in node:
  405. 0 && (module.exports = {
  406. Frame,
  407. verifyLoadState
  408. });