UNPKG

flagpole

Version:

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

425 lines 16.8 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.AppiumElement = void 0; const fs_1 = require("fs"); const Jimp = require("jimp"); const dom_element_1 = require("../html/dom-element"); const value_promise_1 = require("../value-promise"); const jpath_1 = require("../json/jpath"); const helpers_1 = require("../helpers"); const appium_helpers_1 = require("./appium-helpers"); const fs = fs_1.promises; class AppiumElement extends dom_element_1.DOMElement { constructor(input, context, name, elementId) { super(input, context, name || "Appium Element", input); this._elementId = elementId || ""; } get session() { return this.context.response; } static create(input, context, name, elementId) { return __awaiter(this, void 0, void 0, function* () { const element = new AppiumElement(input, context, name, elementId); element._tagName = yield element._getTagName(); if (name === null || name === "") { if (element._tagName !== null) { element._name = `<${element.tagName}>`; } } return element; }); } click(opts) { if (!opts) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this.session.post(`element/${this._elementId}/click`, {}); return this; })); } return this.tap(opts); } find(selector, a, b) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const params = helpers_1.getFindParams(a, b); if (params.matches) { throw "Appium does not support finding element by RegEx"; } else if (params.contains || params.opts) { return helpers_1.findOne(this, selector, params); } const usingValue = selector.split(/\/(.+)/); const res = yield this.session.post(`element/${this._elementId}/element`, { using: usingValue[0], value: usingValue[1], }); if (res.jsonRoot.value.ELEMENT) { const element = yield AppiumElement.create(selector, this.session.context, selector, res.jsonRoot.value.ELEMENT); return element; } else { return helpers_1.wrapAsValue(this.session.context, null, selector); } })); } findAll(selector, a, b) { var _a; return __awaiter(this, void 0, void 0, function* () { const usingValue = selector.split(/\/(.+)/); let elements = []; const params = helpers_1.getFindParams(a, b); let res = new jpath_1.JsonDoc({}); if (params.matches) { throw "Appium does not support finding elements by RegEx"; } else if (params.contains) { if (this.session.capabilities.automationName.toLowerCase() === "uiautomator2") { const values = yield appium_helpers_1.appiumFindByUiAutomator(this.session, selector, params.contains, params.opts, this._elementId); for (let i = 0; i < (values === null || values === void 0 ? void 0 : values.length); i++) { const element = yield AppiumElement.create(selector, this.session.context, selector, values[i].$); elements.push(element); } return elements; } else if (this.session.capabilities.automationName.toLowerCase() === "espresso") { res = yield this.session.post(`element/${this._elementId}/elements`, { using: "text", value: params.contains, }); } else if (this.session.capabilities.automationName.toLowerCase() === "xcuitest") { res = yield this.session.post(`element/${this._elementId}/elements`, { using: "-ios predicate string", value: `label == "${params.contains}"`, }); } } else { res = yield this.session.post(`element/${this._elementId}/elements`, { using: usingValue[0], value: usingValue[1], }); } for (let i = 0; i < ((_a = res.jsonRoot.value) === null || _a === void 0 ? void 0 : _a.length); i++) { elements.push(yield AppiumElement.create(selector, this.context, selector, res.jsonRoot.value[i].ELEMENT)); } if (params.opts) { elements = helpers_1.applyOffsetAndLimit(params.opts, elements); } return elements; }); } type(input) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { var _a; const res = yield this.session.post(`element/${this._elementId}/value`, { text: input, }); if ((_a = res.jsonRoot.value) === null || _a === void 0 ? void 0 : _a.error) { throw "Element cannot be typed into. Did you choose the correct element?"; } return this; })); } clear() { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this.session.post(`element/${this._elementId}/clear`, {}); return this; })); } clearThenType(input) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { yield this.clear(); yield this.type(input); return this; })); } isVisible() { return __awaiter(this, void 0, void 0, function* () { const res = yield this.session.get(`element/${this._elementId}/displayed`); return !!res.jsonRoot.value; }); } getBounds() { return __awaiter(this, void 0, void 0, function* () { const res = yield this.session.get(`element/${this._elementId}/rect`); if (res.jsonRoot.value.error) return null; const bounds = { x: res.jsonRoot.value.x, y: res.jsonRoot.value.y, height: res.jsonRoot.value.height, width: res.jsonRoot.value.width, left: res.jsonRoot.value.x, right: res.jsonRoot.value.x + res.jsonRoot.value.width, top: res.jsonRoot.value.y, bottom: res.jsonRoot.value.y + res.jsonRoot.value.height, middle: { x: res.jsonRoot.value.x + res.jsonRoot.value.width / 2, y: res.jsonRoot.value.y + res.jsonRoot.value.height / 2, }, points: [ { x: res.jsonRoot.value.x, y: res.jsonRoot.value.y, }, { x: res.jsonRoot.value.x + res.jsonRoot.value.width / 2, y: res.jsonRoot.value.y + res.jsonRoot.value.height / 2, }, { x: res.jsonRoot.value.x + res.jsonRoot.value.width, y: res.jsonRoot.value.y + res.jsonRoot.value.height, }, ], }; return bounds; }); } gesture(type, opts) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const bounds = yield this.getBounds(); if (!bounds) throw "Error: element bounds not acquired"; if (!opts.amount) { opts.amount = [bounds.width / 2, bounds.height / 2]; } const start = { pointer1: type == "stretch" ? [bounds.middle.x - 10, bounds.middle.y - 10] : [bounds.left, bounds.top], pointer2: type == "stretch" ? [bounds.middle.x + 10, bounds.middle.y + 10] : [bounds.right, bounds.bottom], }; const end = { pointer1: type == "stretch" ? [ start.pointer1[0] - opts.amount[0], start.pointer1[1] - opts.amount[1], ] : [ start.pointer1[0] + opts.amount[0], start.pointer1[1] + opts.amount[1], ], pointer2: type == "stretch" ? [ start.pointer2[0] + opts.amount[0], start.pointer2[1] + opts.amount[1], ] : [ start.pointer2[0] - opts.amount[0], start.pointer2[1] - opts.amount[1], ], }; yield this.session.movePointer({ type: "touch", duration: opts.duration || 500, start: start.pointer1, end: end.pointer1, }, { type: "touch", duration: opts.duration || 500, start: start.pointer2, end: end.pointer2, }); return this; })); } tap(opts) { return value_promise_1.ValuePromise.execute(() => __awaiter(this, void 0, void 0, function* () { const bounds = yield this.getBounds(); if (!bounds) throw "Error: element bounds not acquired"; const duration = opts.duration || 200; const count = opts.count || 1; const delay = opts.delay || 200; const type = opts.type || "touch"; for (let i = 0; i < count; i++) { yield this.session.movePointer({ type, duration, start: [bounds.middle.x, bounds.middle.y], }); yield this.context.pause(delay); } return this; })); } longpress(opts) { return this.tap({ type: opts.type || "touch", duration: opts.duration || 2000, delay: opts.delay || 200, count: opts.count || 1, }); } _getValue() { return __awaiter(this, void 0, void 0, function* () { throw "_getValue not implemented"; }); } _getText() { return __awaiter(this, void 0, void 0, function* () { const res = yield this.session.get(`element/${this._elementId}/text`); return res.jsonRoot.value; }); } _getTagName() { return __awaiter(this, void 0, void 0, function* () { const res = yield this.session.get(`element/${this._elementId}/name`); return res.jsonRoot.value || null; }); } _getProperty(property) { return __awaiter(this, void 0, void 0, function* () { const res = yield this.session.get(`element/${this._elementId}/css/${property}`); return res.jsonRoot.value || null; }); } _getOuterHtml() { return __awaiter(this, void 0, void 0, function* () { throw "_getOuterHtml not implemented"; }); } _getInnerHtml() { return __awaiter(this, void 0, void 0, function* () { throw "_getInnerHtml not implemented"; }); } _getInnerText() { return __awaiter(this, void 0, void 0, function* () { throw "_getInnerText not implemented"; }); } _getClassName() { return __awaiter(this, void 0, void 0, function* () { throw "_getClassName not implemented"; }); } _getAttribute(key) { return __awaiter(this, void 0, void 0, function* () { const possibleAttributesAndroid = [ "checkable", "checked", "class", "className", "clickable", "content-desc", "contentDescription", "enabled", "focusable", "focused", "long-clickable", "longClickable", "package", "password", "resource-id", "resourceId", "scrollable", "selection-start", "selection-end", "selected", "text", "name", "bounds", "displayed", "contentSize", ]; const possibleAttributesIos = [ "accessibilityContainer", "accessible", "enabled", "frame", "index", "label", "name", "rect", "selected", "type", "value", "visible", "wdAccessibilityContainer", "wdAccessible", "wdEnabled", "wdFrame", "wdIndex", "wdLabel", "wdName", "wdRect", "wdSelected", "wdType", "wdUID", "wdValue", "wdVisible", ]; if (this.session.isAndroid && !possibleAttributesAndroid.includes(key)) { throw `Invalid attribute: must be one of ${possibleAttributesAndroid.join(", ")}`; } else if (this.session.isIos && !possibleAttributesIos.includes(key)) { throw `Invalid attribute: must be one of ${possibleAttributesIos.join(", ")}`; } const res = yield this.session.get(`element/${this._elementId}/attribute/${key}`); return res.jsonRoot.value; }); } screenshot(a, b) { return __awaiter(this, void 0, void 0, function* () { const opts = (typeof a !== "string" ? a : b) || {}; let localFilePath = typeof a == "string" ? a : undefined; if (!localFilePath && opts.path) { localFilePath = opts.path; } const bounds = yield this.getBounds(); const res = yield this.session.get("screenshot"); const encodedData = res.jsonRoot.value; let buff = Buffer.from(encodedData, "base64"); let x = bounds.x; let y = bounds.y; let width = bounds.width; let height = bounds.height; if (opts.clip) { x = opts.clip.x + bounds.x; y = opts.clip.y + bounds.y; width = opts.clip.width; height = opts.clip.height; } yield Jimp.read(buff) .then((image) => { image .crop(x, y, width, height) .quality(100) .getBufferAsync(Jimp.MIME_PNG) .then((buffer) => { buff = buffer; }) .catch((err) => { if (err) return err; }); }) .catch((err) => { if (err) return err; }); if (localFilePath) { yield fs.writeFile(localFilePath, buff); } return buff; }); } toString() { return this._elementId; } } exports.AppiumElement = AppiumElement; //# sourceMappingURL=appium-element.js.map