UNPKG

flagpole

Version:

Simple and fast DOM integration, headless or headful browser, and REST API testing framework.

478 lines 22.4 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BrowserElement = void 0; const puppeteer_element_1 = require("./puppeteer-element"); const util_1 = require("../util"); const csstoxpath_1 = require("csstoxpath"); const value_promise_1 = require("../value-promise"); class BrowserElement extends puppeteer_element_1.PuppeteerElement { constructor(input, context, name, path) { super(input, context, name, path); this._input = input; this._path = path || ""; } get $() { return this._input; } static create(input, context, name, path) { return new Promise((resolve) => { const element = new BrowserElement(input, context, name, path); if (name === null) { element._name = String(path); } Promise.all([element._getTagName(), element._getSourceCode()]).then(() => { resolve(element); }); }); } find(selector) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const element = yield this.$.$(selector); const name = `${selector} under ${this.name}`; const path = `${this.path} ${selector}`; if (element !== null) { return BrowserElement.create(element, this.context, name, path); } return this._wrapAsValue(null, name); })); } findAll(selector) { return __awaiter(this, void 0, void 0, function* () { const elements = yield this.$.$$(selector); const out = []; yield util_1.asyncForEach(elements, (element, i) => __awaiter(this, void 0, void 0, function* () { out.push(yield BrowserElement.create(element, this.context, `${selector}[${i}] under ${this.name}`, `${this.path} ${selector}[${i}]`)); })); return out; }); } getAncestors(selector) { return __awaiter(this, void 0, void 0, function* () { return this._elementHandlesToValueArray(yield this._xQuery("ancestor::", selector), `Ancestors ${selector} of ${this.name}`, `${this.path}[ancestor::${selector}]`); }); } getAncestorOrSelf(selector) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { return this._elementHandlesToFirstValue(yield this._xQuery("ancestor-or-self::", selector, "[1]"), `Ansestor or self ${selector} of ${this.name}`, `ancestor-or-self::${selector}[1]`); })); } getFirstChild(selector) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { return this._elementHandlesToFirstValue(yield this._xQuery("child::", selector, "[1]"), `Child ${selector} of ${this.name}`, `child::${selector}[1]`); })); } getLastChild(selector) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { return this._elementHandlesToFirstValue(yield this._xQuery("child::", selector, "[last()]"), `Last child ${selector} of ${this.name}`, `child::${selector}[last()]`); })); } getFirstSibling(selector) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const siblings = yield this.getSiblings(selector); return siblings[0]; })); } getLastSibling(selector) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const siblings = yield this.getSiblings(selector); return siblings[siblings.length - 1]; })); } getChildOrSelf(selector) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const self = yield this._xQuery("self::", selector); const elements = self.length ? self : yield this._xQuery("child::", selector); return this._elementHandlesToFirstValue(elements, `Child or self ${selector} of ${this.name}`, `self or child::${selector}[0]`); })); } getDescendantOrSelf(selector) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { return this._elementHandlesToFirstValue(yield this._xQuery("descendant-or-self::", selector), `Descendant or self ${selector} of ${this.name}`, `descendant-or-self::${selector}[0]`); })); } getDescendants(selector) { return __awaiter(this, void 0, void 0, function* () { return this._elementHandlesToValueArray(yield this._xQuery("descendant::", selector), `Descendants ${selector} of ${this.name}`, `${this.path}[descendant::${selector}]`); }); } getAncestor(selector = "*") { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const closest = yield this._xQuery("ancestor::", selector); const name = `Ancestor ${selector} of ${this.name}`; const path = `${this.path}[ancestor::${selector}]`; return closest.length > 0 ? BrowserElement.create(closest[0], this.context, name, path) : this._wrapAsValue(null, name, this); })); } getChildren(selector = "*") { return __awaiter(this, void 0, void 0, function* () { const children = yield this._xQuery("child::", selector); const out = []; yield util_1.asyncForEach(children, (child, i) => __awaiter(this, void 0, void 0, function* () { const name = `Child ${selector} ${i} of ${this.name}`; const path = `${this.path}[child::${selector}][${i}]`; out.push(yield BrowserElement.create(child, this.context, name, path)); })); return out; }); } getParent() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const parents = yield this.$.$x(".."); const name = `Parent of ${this.name}`; const path = `${this.path}[..]`; if (parents.length > 0) { return BrowserElement.create(parents[0], this.context, name, path); } return this._wrapAsValue(null, name, this); })); } getSiblings(selector = "*") { return __awaiter(this, void 0, void 0, function* () { const prevSiblings = yield this._xQuery("preceding-sibling::", selector); const nextSiblings = yield this._xQuery("following-sibling::", selector); const siblings = []; yield util_1.asyncForEach(prevSiblings.concat(nextSiblings), (sibling, i) => __awaiter(this, void 0, void 0, function* () { const name = `Sibling ${i} of ${this.name}`; const path = `${this.path}[sibling::${selector}][${i}]`; siblings.push(yield BrowserElement.create(sibling, this.context, name, path)); })); return siblings; }); } getPreviousSibling(selector = "*") { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const siblings = yield this._xQuery("preceding-sibling::", selector); const name = `Previous Sibling of ${this.name}`; const path = `${this.path}[preceding-sibling::${selector}][0]`; if (siblings.length > 0) { return BrowserElement.create(siblings[0], this.context, name, path); } return this._wrapAsValue(null, name, this); })); } getPreviousSiblings(selector = "*") { return __awaiter(this, void 0, void 0, function* () { const siblingElements = yield this._xQuery("preceding-sibling::", selector); const siblings = []; yield util_1.asyncForEach(siblingElements, (sibling, i) => __awaiter(this, void 0, void 0, function* () { const name = `Previous Sibling ${i} of ${this.name}`; const path = `${this.path}[preceding-sibling::${selector}][${i}]`; siblings.push(yield BrowserElement.create(sibling, this.context, name, path)); })); return siblings; }); } getNextSibling(selector = "*") { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const siblings = yield this._xQuery("following-sibling::", selector); const name = `Next Sibling of ${this.name}`; const path = `${this.path}[following-sibling::${selector}][0]`; if (siblings.length > 0) { return BrowserElement.create(siblings[0], this.context, name, path); } return this._wrapAsValue(null, name, this); })); } getNextSiblings(selector = "*") { return __awaiter(this, void 0, void 0, function* () { const siblingElements = yield this._xQuery("following-sibling::", selector); const siblings = []; yield util_1.asyncForEach(siblingElements, (sibling, i) => __awaiter(this, void 0, void 0, function* () { const name = `Next Sibling ${i} of ${this.name}`; const path = `${this.path}/following-sibling::${selector}[${i}]`; siblings.push(yield BrowserElement.create(sibling, this.context, name, path)); })); return siblings; }); } getBounds(boxType = "border") { return __awaiter(this, void 0, void 0, function* () { const allowedTypes = ["content", "padding", "border", "margin"]; if (allowedTypes.indexOf(boxType) < 0) { throw new Error(`${boxType} is not a valid box type. Must be one of the following: ${allowedTypes.join(", ")}.`); } const boxModel = yield this._input.boxModel(); if (boxModel !== null) { return { x: boxModel[boxType][0].x, y: boxModel[boxType][0].y, width: boxModel.width, height: boxModel.height, left: boxModel[boxType][0].x, right: boxModel[boxType][0].x + boxModel.width, top: boxModel[boxType][0].y, bottom: boxModel[boxType][0].y + boxModel.height, middle: { x: boxModel[boxType][0].x + boxModel.width / 2, y: boxModel[boxType][0].y + boxModel.height / 2, }, points: boxModel[boxType], }; } return null; }); } focus() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this._input.focus(); this._completedAction("FOCUS"); return this; })); } blur() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this._input.evaluate((node) => { var _a; return (_a = node.parentElement) === null || _a === void 0 ? void 0 : _a.focus(); }); this._completedAction("BLUR"); return this; })); } hover() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this._input.hover(); this._completedAction("HOVER"); return this; })); } tap() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this._input.tap(); this._completedAction("TAP"); return this; })); } press(key, opts) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this._input.press(key, opts || {}); this._completedAction("PRESS", key); return this; })); } type(textToType, opts = {}) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this._input.type(textToType, opts); this._completedAction("TYPE", (yield this._isPasswordField()) ? textToType.replace(/./g, "*") : textToType); return this; })); } clear() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this._input.click({ clickCount: 3 }); yield this._page.keyboard.press("Backspace"); this._completedAction("CLEAR"); return this; })); } fillForm(a, b) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const isForm = yield this._isFormTag(); if (!isForm) { throw new Error("This is not a form element."); } const attributeName = typeof a === "string" ? a : "name"; const formData = (typeof a === "string" ? b : a) || {}; for (const name in formData) { const value = formData[name]; const selector = `${this._path} [${attributeName}="${name}"]`; const inputs = yield this._page.$$(selector); if (inputs.length == 0) { this.context.logOptionalFailure(`Could not set form field ${name} to ${value}, because the field did not exist.`, selector); } else { const input = inputs[0]; const tagName = String(yield (yield input.getProperty("tagName")).jsonValue()).toLowerCase(); const inputType = String(yield (yield input.getProperty("type")).jsonValue()).toLowerCase(); yield this._page.focus(selector); if (tagName == "select") { yield this._page.select(selector, value); } else if (tagName == "input") { if (inputType == "radio" || inputType == "checkbox") { const multiValues = util_1.toType(value) == "array" ? value : [value]; for (let i = 0; i < inputs.length; i++) { const checkbox = inputs[i]; const isChecked = !!(yield (yield checkbox.getProperty("checked")).jsonValue()); const checkboxValue = String(yield (yield checkbox.getProperty("value")).jsonValue()); if ((multiValues.indexOf(checkboxValue) >= 0 && !isChecked) || (multiValues.indexOf(checkboxValue) < 0 && isChecked)) { yield checkbox.click(); } } } else if (inputType == "button" || inputType == "submit" || inputType == "reset") { } else { yield this.context.clearThenType(selector, value); } } else if (tagName == "button") { } } this._completedAction("FILL"); } return this; })); } submit() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { if (!this._isFormTag()) { throw new Error("You can only use .submit() with a form element."); } const scenario = this.context.scenario; if (scenario.page === null) { throw new Error("Page was null"); } yield scenario.page.evaluate((form) => form.submit(), this.$); this._completedAction("SUBMIT"); return this; })); } click() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { this._completedAction("CLICK"); yield this.$.click(); return this; })); } screenshot(a, b) { const localFilePath = typeof a == "string" ? a : undefined; const opts = (typeof a !== "string" ? a : b) || {}; return this._input.screenshot({ path: localFilePath || opts.path, encoding: "binary", omitBackground: opts.omitBackground || false, }); } selectOption(valuesToSelect) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { valuesToSelect = util_1.toArray(valuesToSelect); this._completedAction("SELECT", valuesToSelect.join(", ")); const valuesSelected = yield this.$.select.apply(this.$, valuesToSelect); this.context .assert(`Select values on ${this.name}`, valuesToSelect.length == valuesSelected.length) .equals(true); return this; })); } pressEnter() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this.$.press("Enter"); this._completedAction("ENTER"); return this; })); } scrollTo() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this.$.evaluate((e) => e.scrollIntoView()); return this; })); } isHidden() { return __awaiter(this, void 0, void 0, function* () { return !(yield this.isVisible()); }); } isVisible() { return __awaiter(this, void 0, void 0, function* () { const isVisibleHandle = yield this._page.evaluateHandle((e) => { const style = window.getComputedStyle(e); return (style && style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0"); }, this.$); const visible = yield isVisibleHandle.jsonValue(); const box = yield this.$.boxModel(); return !!visible && !!box; }); } _getInnerText() { return __awaiter(this, void 0, void 0, function* () { return String(yield this._eval((e) => e.innerText, this.$)); }); } _getInnerHtml() { return __awaiter(this, void 0, void 0, function* () { return String(yield this._eval((e) => e.innerHTML, this.$)); }); } _getOuterHtml() { return __awaiter(this, void 0, void 0, function* () { return String(yield this._eval((e) => e.outerHTML, this.$)); }); } _getValue() { return __awaiter(this, void 0, void 0, function* () { return (yield this._input.getProperty("value")).jsonValue(); }); } _getText() { return __awaiter(this, void 0, void 0, function* () { const textNode = yield this._input.getProperty("textContent"); return String(yield textNode.jsonValue()); }); } _getClassName() { return __awaiter(this, void 0, void 0, function* () { const classNode = yield this._input.getProperty("className"); return String(yield classNode.jsonValue()); }); } _getTagName() { return __awaiter(this, void 0, void 0, function* () { const handle = yield this._input.getProperty("tagName"); const value = String(yield handle.jsonValue()); this._tagName = value.toLowerCase(); return value; }); } _getAttribute(key) { return __awaiter(this, void 0, void 0, function* () { const value = yield this._page.evaluate((el, key) => el.getAttribute(key), this._input, key); return value === null ? null : String(value); }); } _isPasswordField() { return __awaiter(this, void 0, void 0, function* () { return (yield this.getAttribute("type")).$ == "password"; }); } _elementHandlesToFirstValue(elements, name, path) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { return elements.length > 0 ? yield BrowserElement.create(elements[0], this.context, name, path) : this._wrapAsValue(null, name, path); })); } _elementHandlesToValueArray(elements, name, path) { return __awaiter(this, void 0, void 0, function* () { const out = []; yield util_1.asyncMap(elements, (child, i) => __awaiter(this, void 0, void 0, function* () { return yield BrowserElement.create(child, this.context, `${name} [${i}]`, `${path} [${i}]`); })); return out; }); } _xQuery(prefix, selector = "*", suffix = "") { const path = `${prefix}${csstoxpath_1.default(selector)}${suffix}`; return this.$.$x(path); } } exports.BrowserElement = BrowserElement; //# sourceMappingURL=browser-element.js.map