frame.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.Frame = void 0;
  6. exports.verifyLoadState = verifyLoadState;
  7. var _utils = require("../utils");
  8. var _channelOwner = require("./channelOwner");
  9. var _locator = require("./locator");
  10. var _locatorUtils = require("../utils/isomorphic/locatorUtils");
  11. var _elementHandle = require("./elementHandle");
  12. var _jsHandle = require("./jsHandle");
  13. var _fs = _interopRequireDefault(require("fs"));
  14. var network = _interopRequireWildcard(require("./network"));
  15. var _events = require("events");
  16. var _waiter = require("./waiter");
  17. var _events2 = require("./events");
  18. var _types = require("./types");
  19. var _network2 = require("../utils/network");
  20. function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
  21. function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
  22. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  23. /**
  24. * Copyright 2017 Google Inc. All rights reserved.
  25. * Modifications copyright (c) Microsoft Corporation.
  26. *
  27. * Licensed under the Apache License, Version 2.0 (the "License");
  28. * you may not use this file except in compliance with the License.
  29. * You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing, software
  34. * distributed under the License is distributed on an "AS IS" BASIS,
  35. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  36. * See the License for the specific language governing permissions and
  37. * limitations under the License.
  38. */
  39. class Frame extends _channelOwner.ChannelOwner {
  40. static from(frame) {
  41. return frame._object;
  42. }
  43. static fromNullable(frame) {
  44. return frame ? Frame.from(frame) : null;
  45. }
  46. constructor(parent, type, guid, initializer) {
  47. super(parent, type, guid, initializer);
  48. this._eventEmitter = void 0;
  49. this._loadStates = void 0;
  50. this._parentFrame = null;
  51. this._url = '';
  52. this._name = '';
  53. this._detached = false;
  54. this._childFrames = new Set();
  55. this._page = void 0;
  56. this._eventEmitter = new _events.EventEmitter();
  57. this._eventEmitter.setMaxListeners(0);
  58. this._parentFrame = Frame.fromNullable(initializer.parentFrame);
  59. if (this._parentFrame) this._parentFrame._childFrames.add(this);
  60. this._name = initializer.name;
  61. this._url = initializer.url;
  62. this._loadStates = new Set(initializer.loadStates);
  63. this._channel.on('loadstate', event => {
  64. if (event.add) {
  65. this._loadStates.add(event.add);
  66. this._eventEmitter.emit('loadstate', event.add);
  67. }
  68. if (event.remove) this._loadStates.delete(event.remove);
  69. if (!this._parentFrame && event.add === 'load' && this._page) this._page.emit(_events2.Events.Page.Load, this._page);
  70. if (!this._parentFrame && event.add === 'domcontentloaded' && this._page) this._page.emit(_events2.Events.Page.DOMContentLoaded, this._page);
  71. });
  72. this._channel.on('navigated', event => {
  73. this._url = event.url;
  74. this._name = event.name;
  75. this._eventEmitter.emit('navigated', event);
  76. if (!event.error && this._page) this._page.emit(_events2.Events.Page.FrameNavigated, this);
  77. });
  78. }
  79. page() {
  80. return this._page;
  81. }
  82. async goto(url, options = {}) {
  83. const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
  84. return network.Response.fromNullable((await this._channel.goto({
  85. url,
  86. ...options,
  87. waitUntil
  88. })).response);
  89. }
  90. _setupNavigationWaiter(options) {
  91. const waiter = new _waiter.Waiter(this._page, '');
  92. if (this._page.isClosed()) waiter.rejectImmediately(this._page._closeErrorWithReason());
  93. waiter.rejectOnEvent(this._page, _events2.Events.Page.Close, () => this._page._closeErrorWithReason());
  94. waiter.rejectOnEvent(this._page, _events2.Events.Page.Crash, new Error('Navigation failed because page crashed!'));
  95. waiter.rejectOnEvent(this._page, _events2.Events.Page.FrameDetached, new Error('Navigating frame was detached!'), frame => frame === this);
  96. const timeout = this._page._timeoutSettings.navigationTimeout(options);
  97. waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded.`);
  98. return waiter;
  99. }
  100. async waitForNavigation(options = {}) {
  101. return await this._page._wrapApiCall(async () => {
  102. const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
  103. const waiter = this._setupNavigationWaiter(options);
  104. const toUrl = typeof options.url === 'string' ? ` to "${options.url}"` : '';
  105. waiter.log(`waiting for navigation${toUrl} until "${waitUntil}"`);
  106. const navigatedEvent = await waiter.waitForEvent(this._eventEmitter, 'navigated', event => {
  107. var _this$_page;
  108. // Any failed navigation results in a rejection.
  109. if (event.error) return true;
  110. waiter.log(` navigated to "${event.url}"`);
  111. return (0, _network2.urlMatches)((_this$_page = this._page) === null || _this$_page === void 0 ? void 0 : _this$_page.context()._options.baseURL, event.url, options.url);
  112. });
  113. if (navigatedEvent.error) {
  114. const e = new Error(navigatedEvent.error);
  115. e.stack = '';
  116. await waiter.waitForPromise(Promise.reject(e));
  117. }
  118. if (!this._loadStates.has(waitUntil)) {
  119. await waiter.waitForEvent(this._eventEmitter, 'loadstate', s => {
  120. waiter.log(` "${s}" event fired`);
  121. return s === waitUntil;
  122. });
  123. }
  124. const request = navigatedEvent.newDocument ? network.Request.fromNullable(navigatedEvent.newDocument.request) : null;
  125. const response = request ? await waiter.waitForPromise(request._finalRequest()._internalResponse()) : null;
  126. waiter.dispose();
  127. return response;
  128. });
  129. }
  130. async waitForLoadState(state = 'load', options = {}) {
  131. state = verifyLoadState('state', state);
  132. return await this._page._wrapApiCall(async () => {
  133. const waiter = this._setupNavigationWaiter(options);
  134. if (this._loadStates.has(state)) {
  135. waiter.log(` not waiting, "${state}" event already fired`);
  136. } else {
  137. await waiter.waitForEvent(this._eventEmitter, 'loadstate', s => {
  138. waiter.log(` "${s}" event fired`);
  139. return s === state;
  140. });
  141. }
  142. waiter.dispose();
  143. });
  144. }
  145. async waitForURL(url, options = {}) {
  146. var _this$_page2;
  147. if ((0, _network2.urlMatches)((_this$_page2 = this._page) === null || _this$_page2 === void 0 ? void 0 : _this$_page2.context()._options.baseURL, this.url(), url)) return await this.waitForLoadState(options.waitUntil, options);
  148. await this.waitForNavigation({
  149. url,
  150. ...options
  151. });
  152. }
  153. async frameElement() {
  154. return _elementHandle.ElementHandle.from((await this._channel.frameElement()).element);
  155. }
  156. async evaluateHandle(pageFunction, arg) {
  157. (0, _jsHandle.assertMaxArguments)(arguments.length, 2);
  158. const result = await this._channel.evaluateExpressionHandle({
  159. expression: String(pageFunction),
  160. isFunction: typeof pageFunction === 'function',
  161. arg: (0, _jsHandle.serializeArgument)(arg)
  162. });
  163. return _jsHandle.JSHandle.from(result.handle);
  164. }
  165. async evaluate(pageFunction, arg) {
  166. (0, _jsHandle.assertMaxArguments)(arguments.length, 2);
  167. const result = await this._channel.evaluateExpression({
  168. expression: String(pageFunction),
  169. isFunction: typeof pageFunction === 'function',
  170. arg: (0, _jsHandle.serializeArgument)(arg)
  171. });
  172. return (0, _jsHandle.parseResult)(result.value);
  173. }
  174. async _evaluateExposeUtilityScript(pageFunction, arg) {
  175. (0, _jsHandle.assertMaxArguments)(arguments.length, 2);
  176. const result = await this._channel.evaluateExpression({
  177. expression: String(pageFunction),
  178. isFunction: typeof pageFunction === 'function',
  179. exposeUtilityScript: true,
  180. arg: (0, _jsHandle.serializeArgument)(arg)
  181. });
  182. return (0, _jsHandle.parseResult)(result.value);
  183. }
  184. async $(selector, options) {
  185. const result = await this._channel.querySelector({
  186. selector,
  187. ...options
  188. });
  189. return _elementHandle.ElementHandle.fromNullable(result.element);
  190. }
  191. async waitForSelector(selector, options = {}) {
  192. if (options.visibility) throw new Error('options.visibility is not supported, did you mean options.state?');
  193. if (options.waitFor && options.waitFor !== 'visible') throw new Error('options.waitFor is not supported, did you mean options.state?');
  194. const result = await this._channel.waitForSelector({
  195. selector,
  196. ...options
  197. });
  198. return _elementHandle.ElementHandle.fromNullable(result.element);
  199. }
  200. async dispatchEvent(selector, type, eventInit, options = {}) {
  201. await this._channel.dispatchEvent({
  202. selector,
  203. type,
  204. eventInit: (0, _jsHandle.serializeArgument)(eventInit),
  205. ...options
  206. });
  207. }
  208. async $eval(selector, pageFunction, arg) {
  209. (0, _jsHandle.assertMaxArguments)(arguments.length, 3);
  210. const result = await this._channel.evalOnSelector({
  211. selector,
  212. expression: String(pageFunction),
  213. isFunction: typeof pageFunction === 'function',
  214. arg: (0, _jsHandle.serializeArgument)(arg)
  215. });
  216. return (0, _jsHandle.parseResult)(result.value);
  217. }
  218. async $$eval(selector, pageFunction, arg) {
  219. (0, _jsHandle.assertMaxArguments)(arguments.length, 3);
  220. const result = await this._channel.evalOnSelectorAll({
  221. selector,
  222. expression: String(pageFunction),
  223. isFunction: typeof pageFunction === 'function',
  224. arg: (0, _jsHandle.serializeArgument)(arg)
  225. });
  226. return (0, _jsHandle.parseResult)(result.value);
  227. }
  228. async $$(selector) {
  229. const result = await this._channel.querySelectorAll({
  230. selector
  231. });
  232. return result.elements.map(e => _elementHandle.ElementHandle.from(e));
  233. }
  234. async _queryCount(selector) {
  235. return (await this._channel.queryCount({
  236. selector
  237. })).value;
  238. }
  239. async content() {
  240. return (await this._channel.content()).value;
  241. }
  242. async setContent(html, options = {}) {
  243. const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
  244. await this._channel.setContent({
  245. html,
  246. ...options,
  247. waitUntil
  248. });
  249. }
  250. name() {
  251. return this._name || '';
  252. }
  253. url() {
  254. return this._url;
  255. }
  256. parentFrame() {
  257. return this._parentFrame;
  258. }
  259. childFrames() {
  260. return Array.from(this._childFrames);
  261. }
  262. isDetached() {
  263. return this._detached;
  264. }
  265. async addScriptTag(options = {}) {
  266. const copy = {
  267. ...options
  268. };
  269. if (copy.path) {
  270. copy.content = (await _fs.default.promises.readFile(copy.path)).toString();
  271. copy.content += '//# sourceURL=' + copy.path.replace(/\n/g, '');
  272. }
  273. return _elementHandle.ElementHandle.from((await this._channel.addScriptTag({
  274. ...copy
  275. })).element);
  276. }
  277. async addStyleTag(options = {}) {
  278. const copy = {
  279. ...options
  280. };
  281. if (copy.path) {
  282. copy.content = (await _fs.default.promises.readFile(copy.path)).toString();
  283. copy.content += '/*# sourceURL=' + copy.path.replace(/\n/g, '') + '*/';
  284. }
  285. return _elementHandle.ElementHandle.from((await this._channel.addStyleTag({
  286. ...copy
  287. })).element);
  288. }
  289. async click(selector, options = {}) {
  290. return await this._channel.click({
  291. selector,
  292. ...options
  293. });
  294. }
  295. async dblclick(selector, options = {}) {
  296. return await this._channel.dblclick({
  297. selector,
  298. ...options
  299. });
  300. }
  301. async dragAndDrop(source, target, options = {}) {
  302. return await this._channel.dragAndDrop({
  303. source,
  304. target,
  305. ...options
  306. });
  307. }
  308. async tap(selector, options = {}) {
  309. return await this._channel.tap({
  310. selector,
  311. ...options
  312. });
  313. }
  314. async fill(selector, value, options = {}) {
  315. return await this._channel.fill({
  316. selector,
  317. value,
  318. ...options
  319. });
  320. }
  321. async _highlight(selector) {
  322. return await this._channel.highlight({
  323. selector
  324. });
  325. }
  326. locator(selector, options) {
  327. return new _locator.Locator(this, selector, options);
  328. }
  329. getByTestId(testId) {
  330. return this.locator((0, _locatorUtils.getByTestIdSelector)((0, _locator.testIdAttributeName)(), testId));
  331. }
  332. getByAltText(text, options) {
  333. return this.locator((0, _locatorUtils.getByAltTextSelector)(text, options));
  334. }
  335. getByLabel(text, options) {
  336. return this.locator((0, _locatorUtils.getByLabelSelector)(text, options));
  337. }
  338. getByPlaceholder(text, options) {
  339. return this.locator((0, _locatorUtils.getByPlaceholderSelector)(text, options));
  340. }
  341. getByText(text, options) {
  342. return this.locator((0, _locatorUtils.getByTextSelector)(text, options));
  343. }
  344. getByTitle(text, options) {
  345. return this.locator((0, _locatorUtils.getByTitleSelector)(text, options));
  346. }
  347. getByRole(role, options = {}) {
  348. return this.locator((0, _locatorUtils.getByRoleSelector)(role, options));
  349. }
  350. frameLocator(selector) {
  351. return new _locator.FrameLocator(this, selector);
  352. }
  353. async focus(selector, options = {}) {
  354. await this._channel.focus({
  355. selector,
  356. ...options
  357. });
  358. }
  359. async textContent(selector, options = {}) {
  360. const value = (await this._channel.textContent({
  361. selector,
  362. ...options
  363. })).value;
  364. return value === undefined ? null : value;
  365. }
  366. async innerText(selector, options = {}) {
  367. return (await this._channel.innerText({
  368. selector,
  369. ...options
  370. })).value;
  371. }
  372. async innerHTML(selector, options = {}) {
  373. return (await this._channel.innerHTML({
  374. selector,
  375. ...options
  376. })).value;
  377. }
  378. async getAttribute(selector, name, options = {}) {
  379. const value = (await this._channel.getAttribute({
  380. selector,
  381. name,
  382. ...options
  383. })).value;
  384. return value === undefined ? null : value;
  385. }
  386. async inputValue(selector, options = {}) {
  387. return (await this._channel.inputValue({
  388. selector,
  389. ...options
  390. })).value;
  391. }
  392. async isChecked(selector, options = {}) {
  393. return (await this._channel.isChecked({
  394. selector,
  395. ...options
  396. })).value;
  397. }
  398. async isDisabled(selector, options = {}) {
  399. return (await this._channel.isDisabled({
  400. selector,
  401. ...options
  402. })).value;
  403. }
  404. async isEditable(selector, options = {}) {
  405. return (await this._channel.isEditable({
  406. selector,
  407. ...options
  408. })).value;
  409. }
  410. async isEnabled(selector, options = {}) {
  411. return (await this._channel.isEnabled({
  412. selector,
  413. ...options
  414. })).value;
  415. }
  416. async isHidden(selector, options = {}) {
  417. return (await this._channel.isHidden({
  418. selector,
  419. ...options
  420. })).value;
  421. }
  422. async isVisible(selector, options = {}) {
  423. return (await this._channel.isVisible({
  424. selector,
  425. ...options
  426. })).value;
  427. }
  428. async hover(selector, options = {}) {
  429. await this._channel.hover({
  430. selector,
  431. ...options
  432. });
  433. }
  434. async selectOption(selector, values, options = {}) {
  435. return (await this._channel.selectOption({
  436. selector,
  437. ...(0, _elementHandle.convertSelectOptionValues)(values),
  438. ...options
  439. })).values;
  440. }
  441. async setInputFiles(selector, files, options = {}) {
  442. const converted = await (0, _elementHandle.convertInputFiles)(files, this.page().context());
  443. await this._channel.setInputFiles({
  444. selector,
  445. ...converted,
  446. ...options
  447. });
  448. }
  449. async type(selector, text, options = {}) {
  450. await this._channel.type({
  451. selector,
  452. text,
  453. ...options
  454. });
  455. }
  456. async press(selector, key, options = {}) {
  457. await this._channel.press({
  458. selector,
  459. key,
  460. ...options
  461. });
  462. }
  463. async check(selector, options = {}) {
  464. await this._channel.check({
  465. selector,
  466. ...options
  467. });
  468. }
  469. async uncheck(selector, options = {}) {
  470. await this._channel.uncheck({
  471. selector,
  472. ...options
  473. });
  474. }
  475. async setChecked(selector, checked, options) {
  476. if (checked) await this.check(selector, options);else await this.uncheck(selector, options);
  477. }
  478. async waitForTimeout(timeout) {
  479. await this._channel.waitForTimeout({
  480. timeout
  481. });
  482. }
  483. async waitForFunction(pageFunction, arg, options = {}) {
  484. if (typeof options.polling === 'string') (0, _utils.assert)(options.polling === 'raf', 'Unknown polling option: ' + options.polling);
  485. const result = await this._channel.waitForFunction({
  486. ...options,
  487. pollingInterval: options.polling === 'raf' ? undefined : options.polling,
  488. expression: String(pageFunction),
  489. isFunction: typeof pageFunction === 'function',
  490. arg: (0, _jsHandle.serializeArgument)(arg)
  491. });
  492. return _jsHandle.JSHandle.from(result.handle);
  493. }
  494. async title() {
  495. return (await this._channel.title()).value;
  496. }
  497. }
  498. exports.Frame = Frame;
  499. function verifyLoadState(name, waitUntil) {
  500. if (waitUntil === 'networkidle0') waitUntil = 'networkidle';
  501. if (!_types.kLifecycleEvents.has(waitUntil)) throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle|commit)`);
  502. return waitUntil;
  503. }