locator.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.Locator = exports.FrameLocator = void 0;
  6. exports.setTestIdAttribute = setTestIdAttribute;
  7. exports.testIdAttributeName = testIdAttributeName;
  8. var util = _interopRequireWildcard(require("util"));
  9. var _utils = require("../utils");
  10. var _elementHandle = require("./elementHandle");
  11. var _jsHandle = require("./jsHandle");
  12. var _stringUtils = require("../utils/isomorphic/stringUtils");
  13. var _locatorUtils = require("../utils/isomorphic/locatorUtils");
  14. let _util$inspect$custom;
  15. /**
  16. * Copyright (c) Microsoft Corporation.
  17. *
  18. * Licensed under the Apache License, Version 2.0 (the "License");
  19. * you may not use this file except in compliance with the License.
  20. * You may obtain a copy of the License at
  21. *
  22. * http://www.apache.org/licenses/LICENSE-2.0
  23. *
  24. * Unless required by applicable law or agreed to in writing, software
  25. * distributed under the License is distributed on an "AS IS" BASIS,
  26. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  27. * See the License for the specific language governing permissions and
  28. * limitations under the License.
  29. */
  30. 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); }
  31. 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; }
  32. _util$inspect$custom = util.inspect.custom;
  33. class Locator {
  34. constructor(frame, selector, options) {
  35. this._frame = void 0;
  36. this._selector = void 0;
  37. this._frame = frame;
  38. this._selector = selector;
  39. if (options !== null && options !== void 0 && options.hasText) this._selector += ` >> internal:has-text=${(0, _stringUtils.escapeForTextSelector)(options.hasText, false)}`;
  40. if (options !== null && options !== void 0 && options.hasNotText) this._selector += ` >> internal:has-not-text=${(0, _stringUtils.escapeForTextSelector)(options.hasNotText, false)}`;
  41. if (options !== null && options !== void 0 && options.has) {
  42. const locator = options.has;
  43. if (locator._frame !== frame) throw new Error(`Inner "has" locator must belong to the same frame.`);
  44. this._selector += ` >> internal:has=` + JSON.stringify(locator._selector);
  45. }
  46. if (options !== null && options !== void 0 && options.hasNot) {
  47. const locator = options.hasNot;
  48. if (locator._frame !== frame) throw new Error(`Inner "hasNot" locator must belong to the same frame.`);
  49. this._selector += ` >> internal:has-not=` + JSON.stringify(locator._selector);
  50. }
  51. }
  52. async _withElement(task, timeout) {
  53. timeout = this._frame.page()._timeoutSettings.timeout({
  54. timeout
  55. });
  56. const deadline = timeout ? (0, _utils.monotonicTime)() + timeout : 0;
  57. return await this._frame._wrapApiCall(async () => {
  58. const result = await this._frame._channel.waitForSelector({
  59. selector: this._selector,
  60. strict: true,
  61. state: 'attached',
  62. timeout
  63. });
  64. const handle = _elementHandle.ElementHandle.fromNullable(result.element);
  65. if (!handle) throw new Error(`Could not resolve ${this._selector} to DOM Element`);
  66. try {
  67. return await task(handle, deadline ? deadline - (0, _utils.monotonicTime)() : 0);
  68. } finally {
  69. await handle.dispose();
  70. }
  71. });
  72. }
  73. page() {
  74. return this._frame.page();
  75. }
  76. async boundingBox(options) {
  77. return await this._withElement(h => h.boundingBox(), options === null || options === void 0 ? void 0 : options.timeout);
  78. }
  79. async check(options = {}) {
  80. return await this._frame.check(this._selector, {
  81. strict: true,
  82. ...options
  83. });
  84. }
  85. async click(options = {}) {
  86. return await this._frame.click(this._selector, {
  87. strict: true,
  88. ...options
  89. });
  90. }
  91. async dblclick(options = {}) {
  92. return await this._frame.dblclick(this._selector, {
  93. strict: true,
  94. ...options
  95. });
  96. }
  97. async dispatchEvent(type, eventInit = {}, options) {
  98. return await this._frame.dispatchEvent(this._selector, type, eventInit, {
  99. strict: true,
  100. ...options
  101. });
  102. }
  103. async dragTo(target, options = {}) {
  104. return await this._frame.dragAndDrop(this._selector, target._selector, {
  105. strict: true,
  106. ...options
  107. });
  108. }
  109. async evaluate(pageFunction, arg, options) {
  110. return await this._withElement(h => h.evaluate(pageFunction, arg), options === null || options === void 0 ? void 0 : options.timeout);
  111. }
  112. async evaluateAll(pageFunction, arg) {
  113. return await this._frame.$$eval(this._selector, pageFunction, arg);
  114. }
  115. async evaluateHandle(pageFunction, arg, options) {
  116. return await this._withElement(h => h.evaluateHandle(pageFunction, arg), options === null || options === void 0 ? void 0 : options.timeout);
  117. }
  118. async fill(value, options = {}) {
  119. return await this._frame.fill(this._selector, value, {
  120. strict: true,
  121. ...options
  122. });
  123. }
  124. async clear(options = {}) {
  125. return await this.fill('', options);
  126. }
  127. async _highlight() {
  128. // VS Code extension uses this one, keep it for now.
  129. return await this._frame._highlight(this._selector);
  130. }
  131. async highlight() {
  132. return await this._frame._highlight(this._selector);
  133. }
  134. locator(selectorOrLocator, options) {
  135. if ((0, _utils.isString)(selectorOrLocator)) return new Locator(this._frame, this._selector + ' >> ' + selectorOrLocator, options);
  136. if (selectorOrLocator._frame !== this._frame) throw new Error(`Locators must belong to the same frame.`);
  137. return new Locator(this._frame, this._selector + ' >> internal:chain=' + JSON.stringify(selectorOrLocator._selector), options);
  138. }
  139. getByTestId(testId) {
  140. return this.locator((0, _locatorUtils.getByTestIdSelector)(testIdAttributeName(), testId));
  141. }
  142. getByAltText(text, options) {
  143. return this.locator((0, _locatorUtils.getByAltTextSelector)(text, options));
  144. }
  145. getByLabel(text, options) {
  146. return this.locator((0, _locatorUtils.getByLabelSelector)(text, options));
  147. }
  148. getByPlaceholder(text, options) {
  149. return this.locator((0, _locatorUtils.getByPlaceholderSelector)(text, options));
  150. }
  151. getByText(text, options) {
  152. return this.locator((0, _locatorUtils.getByTextSelector)(text, options));
  153. }
  154. getByTitle(text, options) {
  155. return this.locator((0, _locatorUtils.getByTitleSelector)(text, options));
  156. }
  157. getByRole(role, options = {}) {
  158. return this.locator((0, _locatorUtils.getByRoleSelector)(role, options));
  159. }
  160. frameLocator(selector) {
  161. return new FrameLocator(this._frame, this._selector + ' >> ' + selector);
  162. }
  163. filter(options) {
  164. return new Locator(this._frame, this._selector, options);
  165. }
  166. async elementHandle(options) {
  167. return await this._frame.waitForSelector(this._selector, {
  168. strict: true,
  169. state: 'attached',
  170. ...options
  171. });
  172. }
  173. async elementHandles() {
  174. return await this._frame.$$(this._selector);
  175. }
  176. first() {
  177. return new Locator(this._frame, this._selector + ' >> nth=0');
  178. }
  179. last() {
  180. return new Locator(this._frame, this._selector + ` >> nth=-1`);
  181. }
  182. nth(index) {
  183. return new Locator(this._frame, this._selector + ` >> nth=${index}`);
  184. }
  185. and(locator) {
  186. if (locator._frame !== this._frame) throw new Error(`Locators must belong to the same frame.`);
  187. return new Locator(this._frame, this._selector + ` >> internal:and=` + JSON.stringify(locator._selector));
  188. }
  189. or(locator) {
  190. if (locator._frame !== this._frame) throw new Error(`Locators must belong to the same frame.`);
  191. return new Locator(this._frame, this._selector + ` >> internal:or=` + JSON.stringify(locator._selector));
  192. }
  193. async focus(options) {
  194. return await this._frame.focus(this._selector, {
  195. strict: true,
  196. ...options
  197. });
  198. }
  199. async blur(options) {
  200. await this._frame._channel.blur({
  201. selector: this._selector,
  202. strict: true,
  203. ...options
  204. });
  205. }
  206. async count() {
  207. return await this._frame._queryCount(this._selector);
  208. }
  209. async getAttribute(name, options) {
  210. return await this._frame.getAttribute(this._selector, name, {
  211. strict: true,
  212. ...options
  213. });
  214. }
  215. async hover(options = {}) {
  216. return await this._frame.hover(this._selector, {
  217. strict: true,
  218. ...options
  219. });
  220. }
  221. async innerHTML(options) {
  222. return await this._frame.innerHTML(this._selector, {
  223. strict: true,
  224. ...options
  225. });
  226. }
  227. async innerText(options) {
  228. return await this._frame.innerText(this._selector, {
  229. strict: true,
  230. ...options
  231. });
  232. }
  233. async inputValue(options) {
  234. return await this._frame.inputValue(this._selector, {
  235. strict: true,
  236. ...options
  237. });
  238. }
  239. async isChecked(options) {
  240. return await this._frame.isChecked(this._selector, {
  241. strict: true,
  242. ...options
  243. });
  244. }
  245. async isDisabled(options) {
  246. return await this._frame.isDisabled(this._selector, {
  247. strict: true,
  248. ...options
  249. });
  250. }
  251. async isEditable(options) {
  252. return await this._frame.isEditable(this._selector, {
  253. strict: true,
  254. ...options
  255. });
  256. }
  257. async isEnabled(options) {
  258. return await this._frame.isEnabled(this._selector, {
  259. strict: true,
  260. ...options
  261. });
  262. }
  263. async isHidden(options) {
  264. return await this._frame.isHidden(this._selector, {
  265. strict: true,
  266. ...options
  267. });
  268. }
  269. async isVisible(options) {
  270. return await this._frame.isVisible(this._selector, {
  271. strict: true,
  272. ...options
  273. });
  274. }
  275. async press(key, options = {}) {
  276. return await this._frame.press(this._selector, key, {
  277. strict: true,
  278. ...options
  279. });
  280. }
  281. async screenshot(options = {}) {
  282. return await this._withElement((h, timeout) => h.screenshot({
  283. ...options,
  284. timeout
  285. }), options.timeout);
  286. }
  287. async scrollIntoViewIfNeeded(options = {}) {
  288. return await this._withElement((h, timeout) => h.scrollIntoViewIfNeeded({
  289. ...options,
  290. timeout
  291. }), options.timeout);
  292. }
  293. async selectOption(values, options = {}) {
  294. return await this._frame.selectOption(this._selector, values, {
  295. strict: true,
  296. ...options
  297. });
  298. }
  299. async selectText(options = {}) {
  300. return await this._withElement((h, timeout) => h.selectText({
  301. ...options,
  302. timeout
  303. }), options.timeout);
  304. }
  305. async setChecked(checked, options) {
  306. if (checked) await this.check(options);else await this.uncheck(options);
  307. }
  308. async setInputFiles(files, options = {}) {
  309. return await this._frame.setInputFiles(this._selector, files, {
  310. strict: true,
  311. ...options
  312. });
  313. }
  314. async tap(options = {}) {
  315. return await this._frame.tap(this._selector, {
  316. strict: true,
  317. ...options
  318. });
  319. }
  320. async textContent(options) {
  321. return await this._frame.textContent(this._selector, {
  322. strict: true,
  323. ...options
  324. });
  325. }
  326. async type(text, options = {}) {
  327. return await this._frame.type(this._selector, text, {
  328. strict: true,
  329. ...options
  330. });
  331. }
  332. async pressSequentially(text, options = {}) {
  333. return await this.type(text, options);
  334. }
  335. async uncheck(options = {}) {
  336. return await this._frame.uncheck(this._selector, {
  337. strict: true,
  338. ...options
  339. });
  340. }
  341. async all() {
  342. return new Array(await this.count()).fill(0).map((e, i) => this.nth(i));
  343. }
  344. async allInnerTexts() {
  345. return await this._frame.$$eval(this._selector, ee => ee.map(e => e.innerText));
  346. }
  347. async allTextContents() {
  348. return await this._frame.$$eval(this._selector, ee => ee.map(e => e.textContent || ''));
  349. }
  350. async waitFor(options) {
  351. await this._frame._channel.waitForSelector({
  352. selector: this._selector,
  353. strict: true,
  354. omitReturnValue: true,
  355. ...options
  356. });
  357. }
  358. async _expect(expression, options) {
  359. const params = {
  360. selector: this._selector,
  361. expression,
  362. ...options,
  363. isNot: !!options.isNot
  364. };
  365. params.expectedValue = (0, _jsHandle.serializeArgument)(options.expectedValue);
  366. const result = await this._frame._channel.expect(params);
  367. if (result.received !== undefined) result.received = (0, _jsHandle.parseResult)(result.received);
  368. return result;
  369. }
  370. [_util$inspect$custom]() {
  371. return this.toString();
  372. }
  373. toString() {
  374. return (0, _utils.asLocator)('javascript', this._selector);
  375. }
  376. }
  377. exports.Locator = Locator;
  378. class FrameLocator {
  379. constructor(frame, selector) {
  380. this._frame = void 0;
  381. this._frameSelector = void 0;
  382. this._frame = frame;
  383. this._frameSelector = selector;
  384. }
  385. locator(selectorOrLocator, options) {
  386. if ((0, _utils.isString)(selectorOrLocator)) return new Locator(this._frame, this._frameSelector + ' >> internal:control=enter-frame >> ' + selectorOrLocator, options);
  387. if (selectorOrLocator._frame !== this._frame) throw new Error(`Locators must belong to the same frame.`);
  388. return new Locator(this._frame, this._frameSelector + ' >> internal:control=enter-frame >> ' + selectorOrLocator._selector, options);
  389. }
  390. getByTestId(testId) {
  391. return this.locator((0, _locatorUtils.getByTestIdSelector)(testIdAttributeName(), testId));
  392. }
  393. getByAltText(text, options) {
  394. return this.locator((0, _locatorUtils.getByAltTextSelector)(text, options));
  395. }
  396. getByLabel(text, options) {
  397. return this.locator((0, _locatorUtils.getByLabelSelector)(text, options));
  398. }
  399. getByPlaceholder(text, options) {
  400. return this.locator((0, _locatorUtils.getByPlaceholderSelector)(text, options));
  401. }
  402. getByText(text, options) {
  403. return this.locator((0, _locatorUtils.getByTextSelector)(text, options));
  404. }
  405. getByTitle(text, options) {
  406. return this.locator((0, _locatorUtils.getByTitleSelector)(text, options));
  407. }
  408. getByRole(role, options = {}) {
  409. return this.locator((0, _locatorUtils.getByRoleSelector)(role, options));
  410. }
  411. frameLocator(selector) {
  412. return new FrameLocator(this._frame, this._frameSelector + ' >> internal:control=enter-frame >> ' + selector);
  413. }
  414. first() {
  415. return new FrameLocator(this._frame, this._frameSelector + ' >> nth=0');
  416. }
  417. last() {
  418. return new FrameLocator(this._frame, this._frameSelector + ` >> nth=-1`);
  419. }
  420. nth(index) {
  421. return new FrameLocator(this._frame, this._frameSelector + ` >> nth=${index}`);
  422. }
  423. }
  424. exports.FrameLocator = FrameLocator;
  425. let _testIdAttributeName = 'data-testid';
  426. function testIdAttributeName() {
  427. return _testIdAttributeName;
  428. }
  429. function setTestIdAttribute(attributeName) {
  430. _testIdAttributeName = attributeName;
  431. }