UNPKG

@sap_oss/wdio-qmate-service

Version:

[![REUSE status](https://api.reuse.software/badge/github.com/SAP/wdio-qmate-service)](https://api.reuse.software/info/github.com/SAP/wdio-qmate-service)[![Node.js CI](https://github.com/SAP/wdio-qmate-service/actions/workflows/node.js.yml/badge.svg)](http

760 lines 41.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.UserInteraction = void 0; const verboseLogger_1 = require("../../helper/verboseLogger"); const errorHandler_1 = __importDefault(require("../../helper/errorHandler")); const constants_1 = require("../constants"); const userInteraction_constants_1 = require("../common/constants/userInteraction.constants"); /** * @class userInteraction * @memberof ui5 */ class UserInteraction { // =================================== LOGGER=================================== vlf = new verboseLogger_1.VerboseLoggerFactory("ui5", "click"); ErrorHandler = new errorHandler_1.default(); // =================================== CONSTANTS =================================== static TEXTAREA_METADATA = "sap.m.TextArea"; static TEXTAREA_MACROS_METADATA = "sap.fe.macros.field.TextAreaEx"; static SUPPORTED_TEXTAREA_METADATA = [UserInteraction.TEXTAREA_METADATA, UserInteraction.TEXTAREA_MACROS_METADATA]; static SELECT_DEPRECATION_MESSAGE = "This function is deprecated, please use the generic 'ui5.userInteraction.select' function instead."; // =================================== CLICK =================================== /** * @function click * @memberOf ui5.userInteraction * @description Clicks on the element with the given selector. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.click(selector); */ async click(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.click); let elem = null; await browser.waitUntil(async function () { elem = await ui5.element.getDisplayed(selector, index, timeout); if (!elem) return false; return elem.isClickable(); }, { timeout, timeoutMsg: `Element not clickable after ${+timeout / 1000}s` }); try { // @ts-ignore await elem.click(); } catch (error) { // @ts-ignore this.ErrorHandler.logException(error); } } /** * @function clickAndRetry * @memberOf ui5.userInteraction * @description Clicks on the element with the given selector and retries the action in case of a failure. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @param {Number} [retries=3] - The number of retries, can be set in config for all functions under params stepsRetries. * @param {Number} [interval=5000] - The delay between the retries (ms). Can be set in config for all functions under params.stepRetriesIntervals. * @example await ui5.userInteraction.clickAndRetry(selector); */ async clickAndRetry(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT, retries = 3, interval = 5000) { const vl = this.vlf.initLog(this.clickAndRetry); await util.function.retry(this.click, [selector, index, timeout], retries, interval, this); } /** * @function doubleClick * @memberOf ui5.userInteraction * @description Double Clicks on the passed element. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.doubleClick(selector); */ async doubleClick(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.doubleClick); let elem = null; await browser.waitUntil(async function () { elem = await ui5.element.getDisplayed(selector, index, timeout); if (!elem) return false; return elem.isClickable(); }, { timeout, timeoutMsg: `Element not clickable after ${+timeout / 1000}s` }); try { // @ts-ignore await elem.doubleClick(); } catch (error) { // @ts-ignore this.ErrorHandler.logException(error); } } /** * @function rightClick * @memberOf ui5.userInteraction * @description Right Clicks on the passed element. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example const elem = await nonUi5.element.getById("button01"); * await ui5.userInteraction.rightClick(elem); */ async rightClick(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.rightClick); let elem = null; await browser.waitUntil(async function () { elem = await ui5.element.getDisplayed(selector, index, timeout); if (!elem) return false; return elem.isClickable(); }, { timeout, timeoutMsg: `Element not clickable after ${+timeout / 1000}s` }); try { // @ts-ignore await elem.click({ button: "right" }); } catch (error) { // @ts-ignore this.ErrorHandler.logException(error); } } /** * @function clickTab * @memberOf ui5.userInteraction * @description Clicks on the tab with the given selector and checks if the tab got selected successfully. * The function retries the click for maximal 3 times if the selection of the tab (blue underline) was not successful. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.clickTab(selector); */ async clickTab(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.clickTab); await util.function.retry(async (selector, index, timeout) => { await ui5.userInteraction.click(selector, index, timeout); const tabSwitchedSuccessfully = await this._verifyTabSwitch(selector); if (tabSwitchedSuccessfully === false) { this.ErrorHandler.logException(new Error("Could not verify successful tab switch.")); } }, [selector, index, timeout], 3, 5000, this); } /** * @function clickListItem * @memberOf ui5.userInteraction * @description Clicks or opens the list item with the given selector (e.g. ColumnListItem, StandardListItem). * In some cases the default click function is not working correctly (clicks an element within the list item). * Therefore we recommend to use this function to open a specific list item. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.clickListItem(selector); */ async clickListItem(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.clickListItem); const elem = await ui5.element.getDisplayed(selector, index, timeout); await ui5.control.execute(function (control, done) { control.attachPress(function () { done(); }); control.firePress(); }, elem); } // =================================== CHECK =================================== /** * @function check * @memberOf ui5.userInteraction * @description Checks the checkbox with the given selector. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.check(selector); */ async check(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.check); try { const isSelected = await ui5.element.getPropertyValue(selector, "selected", index, timeout); if (!isSelected) { await this.click(selector, index, timeout); } else { vl.log("Checkbox already checked."); } } catch (error) { this.ErrorHandler.logException(error); } } /** * @function uncheck * @memberOf ui5.userInteraction * @description Unchecks the checkbox with the given selector. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.uncheck(selector); */ async uncheck(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.uncheck); try { const isSelected = await ui5.element.getPropertyValue(selector, "selected", index, timeout); if (isSelected) { await this.click(selector, index, timeout); } else { vl.log("Checkbox already unchecked."); } } catch (error) { this.ErrorHandler.logException(error); } } // =================================== FILL =================================== /** * @function fill * @memberOf ui5.userInteraction * @description Fills the input field with the given selector. * @param {Object} selector - The selector describing the element. * @param {String | Number} value - The value to enter. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.fill(selector, "My Value"); */ async fill(selector, value, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.fill); vl.log(`Filling with ${value}`); if (typeof value === "string" || typeof value === "number") { const id = await ui5.element.getId(selector, index, timeout); let elem = null; if (UserInteraction.SUPPORTED_TEXTAREA_METADATA.includes(selector.elementProperties.metadata)) { elem = await nonUi5.element.getByCss("[id='" + id + "'] textarea", 0, timeout); } else { elem = await nonUi5.element.getByCss("[id='" + id + "'] input", 0, timeout); } await elem.setValue(value); } else { this.ErrorHandler.logException(new Error("Please provide an element and value(datatype - number/string) as arguments.")); } } /** * @function fillAndRetry * @memberOf ui5.userInteraction * @description Fills the input field with the given selector and retries the action in case of a failure. * @param {Object} selector - The selector describing the element. * @param {String | Number} value - The value to enter. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @param {Number} [retries=3] - The number of retries, can be set in config for all functions under params stepsRetries. * @param {Number} [interval=5000] - The delay between the retries (ms). Can be set in config for all functions under params.stepRetriesIntervals. * @example await ui5.userInteraction.fillAndRetry(selector, "My Value"); */ async fillAndRetry(selector, value, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT, retries = 3, interval = 5000) { const vl = this.vlf.initLog(this.fillAndRetry); await util.function.retry(this.fill, [selector, value, index, timeout], retries, interval, this); } // =================================== CLEAR =================================== /** * @function clear * @memberOf ui5.userInteraction * @description Clears the input with the given selector. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.clear(selector); */ async clear(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.clear); const id = await ui5.element.getId(selector, index, timeout); // Remove tokens/tags if displayed. Use isDisplayed() instead of isExisting() because // the .sapMTokenizer node can exist in the DOM but be hidden (e.g. when no tokens are present), // which would cause the subsequent click() to fail with a "not displayed" timeout. const tokenizer = $(`[id='${id}'] .sapMTokenizer`); if (await tokenizer.isDisplayed()) { await nonUi5.userInteraction.click(tokenizer); await nonUi5.userInteraction.selectAll(tokenizer, timeout); await common.userInteraction.pressBackspace(); } // Do NOT use webdriverIO clearValue() here! Some of popovers hides after clearValue call instead of stay in focus. // This can lead to the cases when value is cleared but popover closes and discard changes. const isTextArea = UserInteraction.SUPPORTED_TEXTAREA_METADATA.includes(selector.elementProperties.metadata); await browser.execute(function (id, isTextArea) { // @ts-ignore const input = document.getElementById(id).getElementsByTagName(isTextArea ? "textarea" : "input")[0]; input.value = ""; input.focus(); }, id, isTextArea); } /** * @function clearAndRetry * @memberOf ui5.userInteraction * @description Clears the input with the given selector and retries the action in case of a failure * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @param {Number} [retries=3] - The number of retries, can be set in config for all functions under params stepsRetries. * @param {Number} [interval=5000] - The delay between the retries (ms). Can be set in config for all functions under params.stepRetriesIntervals. * @example await ui5.userInteraction.clearAndRetry(selector); */ async clearAndRetry(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT, retries = 3, interval = 5000) { const vl = this.vlf.initLog(this.clearAndRetry); await util.function.retry(this.clear, [selector, index, timeout], retries, interval, this); } /** * @function clearAndFill * @memberOf ui5.userInteraction * @description Clears the input field with the given selector and fills the given value. * @param {Object} selector - The selector describing the element. * @param {String | Number} value - The value to enter. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.clearAndFill(selector, "My Value"); */ async clearAndFill(selector, value, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.clearAndFill); if (typeof value === "number" || typeof value === "string" || typeof value === "boolean") { await this.clear(selector, index, timeout); await common.userInteraction.fillActive(value); } else { this.ErrorHandler.logException(new Error("Please provide a value(datatype - number/string) as second parameter.")); } } /** * @function clearAndFillAndRetry * @memberOf ui5.userInteraction * @description Clears the input field with the given selector and fills the given value. Retries the action in case of a failure. * @param {Object} selector - The selector describing the element. * @param {String} value - The value to enter. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @param {Number} [retries=3] - The number of retries, can be set in config for all functions under params stepsRetries. * @param {Number} [interval=5000] - The delay between the retries (ms). Can be set in config for all functions under params.stepRetriesIntervals. * @param {Boolean} [verify=true] - Specifies if the filled value should be verified. * @example await ui5.userInteraction.clearAndFillAndRetry(selector, "My Value"); */ async clearAndFillAndRetry(selector, value, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT, retries = 3, interval = 5000, verify = true) { const vl = this.vlf.initLog(this.clearAndFillAndRetry); await util.function.retry(async (selector, value, index, timeout) => { await this.clearAndFill(selector, value, index, timeout); if (verify) { const elem = await ui5.element.getDisplayed(selector, index, timeout); let elemValue = await ui5.element.getValue(selector, index, timeout); if (elemValue != value) { // IMPORTANT: keep non-strict comparison for format changes after input (10 -> 10.00) elemValue = await ui5.element.getInnerAttribute(elem, "data-" + "value"); if (elemValue != value) { // IMPORTANT: keep non-strict comparison for format changes after input (10 -> 10.00) throw new Error(`Actual value '${elemValue}' not equal to expected value '${value}'`); } } } }, [selector, value, index, timeout], retries, interval, this); } /** * @function clearSmartFieldInput * @memberOf ui5.userInteraction * @description Clears the smart filed with the given selector. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.clearSmartFieldInput(selector); */ async clearSmartFieldInput(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.clearSmartFieldInput); await ui5.userInteraction.clear(selector, index, timeout); } /** * @function clearAndFillSmartFieldInput * @memberOf ui5.userInteraction * @description Clears the smart filed with the given selector and fills the given value. * @param {Object} selector - The selector describing the element. * @param {String} value - The value to enter. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.clearAndFillSmartFieldInput(selector, "My Value"); */ async clearAndFillSmartFieldInput(selector, value, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.clearAndFillSmartFieldInput); const id = await ui5.element.getId(selector, index, timeout); const elem = await nonUi5.element.getByCss(`input[id*='${id}']`); await elem.click(); await ui5.userInteraction.selectAll(selector, index, timeout); await elem.setValue(value); } /** * @function clearAndFillSmartFieldInputAndRetry * @memberOf ui5.userInteraction * @description Clears the smart filed with the given selector and fills the given value and retries the action in case of a failure. * @param {Object} selector - The selector describing the element. * @param {String} value - The value to enter. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @param {Number} [retries=3] - The number of retries, can be set in config for all functions under params stepsRetries. * @param {Number} [interval=5000] - The delay between the retries (ms). Can be set in config for all functions under params.stepRetriesIntervals. * @example await ui5.userInteraction.clearAndFillSmartFieldInputAndRetry(selector, "My Value"); */ async clearAndFillSmartFieldInputAndRetry(selector, value, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT, retries = 3, interval = 5000) { const vl = this.vlf.initLog(this.clearAndFillSmartFieldInputAndRetry); await util.function.retry(this.clearAndFillSmartFieldInput, [selector, value, index, timeout], retries, interval, this); } // =================================== SELECT =================================== /** * @function select * @memberOf ui5.userInteraction * @description Selects a value from a UI5 dropdown control. * @param {Object} selector - The selector describing the element. * @param {String} value - The value to select. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @example await ui5.userInteraction.select(selector, "Germany"); */ async select(selector, value, index = 0) { const vl = this.vlf.initLog(this.select); await this.clickSelectArrow(selector, index); if (Array.isArray(value)) { await this._selectMultipleOptions(value); } else { await this._selectOption(value); } } async selectBox(selector, value, index = 0) { util.console.warn(UserInteraction.SELECT_DEPRECATION_MESSAGE); await this.select(selector, value, index); } async selectComboBox(selector, value, index = 0) { util.console.warn(UserInteraction.SELECT_DEPRECATION_MESSAGE); await this.select(selector, value, index); } async selectMultiComboBox(selector, values, index = 0) { util.console.warn(UserInteraction.SELECT_DEPRECATION_MESSAGE); await this.select(selector, values, index); } /** * @function clickSelectArrow * @memberOf ui5.userInteraction * @description Clicks the arrow icon at the passed selector (select box). * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @example await ui5.userInteraction.clickSelectArrow(selector); */ async clickSelectArrow(selector, index = 0) { const vl = this.vlf.initLog(this.clickSelectArrow); const id = await ui5.element.getId(selector, index); const cssLookup = nonUi5.element.getByCss(`[id='${id}-arrow']`, 0, 3000); const ui5Lookup = ui5.element.getDisplayed({ elementProperties: { metadata: "sap.ui.core.Icon", src: "*slim-arrow-down" }, ancestorProperties: { id: `*${id}*` } }); const arrow = await Promise.any([cssLookup, ui5Lookup]); await arrow.click(); } /** * @function clickSelectArrowAndRetry * @memberOf ui5.userInteraction * @description Clicks the arrow icon at the passed selector (select box), and retries in case it fails. * @param {Object} selector - The selector describing the element * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [retries=3] - The number of retries, can be set in config for all functions under params stepsRetries. * @param {Number} [interval=5000] - The delay between the retries (ms). Can be set in config for all functions under params.stepRetriesIntervals. * @example await ui5.userInteraction.clickSelectArrowAndRetry(selector); */ async clickSelectArrowAndRetry(selector, index = 0, retries = 3, interval = 5000) { const vl = this.vlf.initLog(this.clickSelectArrowAndRetry); await util.function.retry(this.clickSelectArrow, [selector, index], retries, interval, this); } /** * @function selectFromTab * @memberOf ui5.userInteraction * @description Selects the passed value on the tab with the given selector and checks if the tab got selected successfully. * The function retries the click for maximal 3 times if the selection of the tab (blue underline) was not successful. * @param {Object} selector - The selector describing the element. * @param {String} value - The value to select. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.selectFromTab(selector); */ async selectFromTab(selector, value, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.selectFromTab); await util.function.retry(async (selector, index, timeout) => { const arrowSelector = { elementProperties: { viewName: selector.elementProperties.viewName, metadata: "sap.ui.core.Icon", src: "sap-icon://slim-arrow-down" }, ancestorProperties: selector }; await ui5.userInteraction.click(arrowSelector, index, timeout); const menuItemSelectorOldUI5 = { elementProperties: { viewName: selector.elementProperties.viewName, metadata: "sap.ui.unified.MenuItem", text: value } }; const menuItemSelectorNewUI5 = { elementProperties: { viewName: selector.elementProperties.viewName, metadata: "sap.m.IconTabFilter", text: value } }; await browser.waitUntil(async () => { try { await Promise.any([ui5.userInteraction.click(menuItemSelectorNewUI5, 0, 500), ui5.userInteraction.click(menuItemSelectorOldUI5, 0, 500)]); return true; } catch (error) { // Ignore error and continue to next promise return false; } }, { timeout: timeout, timeoutMsg: "Menu Item not clickable after " + timeout / 1000 + "s", interval: constants_1.GLOBAL_DEFAULT_WAIT_INTERVAL }); const tabSwitchedSuccessfully = await this._verifyTabSwitch(selector); if (tabSwitchedSuccessfully === false) { this.ErrorHandler.logException(new Error("Could not verify successful tab switch.")); } }, [selector, index, timeout], 3, 5000, this); } // =================================== OTHERS =================================== /** * @function mouseOverElement * @memberOf ui5.userInteraction * @description Moves the cursor/focus to the element with the given selector. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.mouseOverElement(selector); */ async mouseOverElement(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.mouseOverElement); let elem; try { elem = await ui5.element.getDisplayed(selector, index, timeout); } catch (error) { return this.ErrorHandler.logException(new Error(), `No element found for selector ${selector}`); } await elem.moveTo(); } /** * @function scrollToElement * @memberOf ui5.userInteraction * @description Scrolls the element with the given selector into view. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {String | Object} [alignment="center"] - The alignment option for scrolling. * Can be one of: "start", "center", "end", "nearest", or an object with properties: * - block: Vertical alignment ("start", "center", "end", "nearest"). * - inline: Horizontal alignment ("start", "center", "end", "nearest"). * @param {Number} [timeout=30000] - The timeout to wait (ms). * * @example * // Scroll to element with center alignment. * await nonUi5.userInteraction.scrollToElement(selector, 0, "center"); * * @example * // Scroll to element with custom alignment. * const alignment = { * block: "start", * inline: "center" * }; * await nonUi5.userInteraction.scrollToElement(selector, 0, alignment); */ async scrollToElement(selector, index = 0, alignment = "center", timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.scrollToElement); let options = {}; const elem = await ui5.element.getDisplayed(selector, index, timeout); if (elem) { if (typeof alignment == "string") { options = { block: alignment, inline: alignment }; } else if (typeof alignment === "object") { options = alignment; } await elem.scrollIntoView(options); } } /** * @function selectAll * @memberOf ui5.userInteraction * @description Performs "select all" (ctrl + a) at the element with the given selector. * @param {Object} [selector] - The selector describing the element. * @param {Number} [index=0] - The index of the selector, in case there are more than one elements visible at the same time. * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.selectAll(selector); */ async selectAll(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.selectAll); if (selector !== undefined) await this.click(selector, index, timeout); else { util.console.info("Selector properties are undefined. Action will be performed on current element."); } await common.userInteraction.pressKey([userInteraction_constants_1.KeyCodes.CONTROL, "a"]); } /** * @function openF4Help * @memberOf ui5.userInteraction * @description Opens the F4-help of the element with the given selector. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @param {Boolean} useF4Key - Specifies if the help is opened by pressing the F4-key or via the button. * The default value is true (triggered by pressing the F4-key). Set "useF4Key" to false, to trigger the search by clicking the button. * @example await ui5.userInteraction.openF4Help(selector, 0, 30000, false); */ async openF4Help(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT, useF4Key = true) { const vl = this.vlf.initLog(this.openF4Help); await ui5.userInteraction.click(selector, index, timeout); if (useF4Key === true) { await common.userInteraction.pressF4(); } else { const id = await ui5.element.getId(selector); const button = await nonUi5.element.getByCss("[id='" + id + "-vhi']", 0, timeout); await button.click(); } } /** * @function searchFor * @memberOf ui5.userInteraction * @description Searches for the passed value and executes the search. * In case that the search is already filled, it will reset the field first. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @param {Boolean} useEnter - Specifies if the search is triggered by pressing the Enter-key or via the search button. * The default value is true (triggered by pressing the Enter-key). Set "useEnter" to false, to trigger the search by clicking the search button. * @example await ui5.userInteraction.searchFor(selector, "My Value", 0, 30000, false); */ async searchFor(selector, value, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT, useEnter = true) { const vl = this.vlf.initLog(this.searchFor); vl.log(`Searching for ${value}`); await ui5.userInteraction.clearAndFillAndRetry(selector, value, index, timeout); if (useEnter === true) { await common.userInteraction.pressEnter(); } else { const id = await ui5.element.getId(selector, index, timeout); const searchButton = await nonUi5.element.getByCss("[id='" + id + "-search']", 0, timeout); await searchButton.click(); } } /** * @function resetSearch * @memberOf ui5.userInteraction * @description Resets the search field. * @param {Object} selector - The selector describing the element. * @param {Number} [index=0] - The index of the selector (in case there are more than one elements visible at the same time). * @param {Number} [timeout=30000] - The timeout to wait (ms). * @example await ui5.userInteraction.resetSearch(selector); */ async resetSearch(selector, index = 0, timeout = parseFloat(process.env.QMATE_CUSTOM_TIMEOUT) || constants_1.GLOBAL_DEFAULT_WAIT_TIMEOUT) { const vl = this.vlf.initLog(this.resetSearch); const id = await ui5.element.getId(selector, index, timeout); const resetButton = await nonUi5.element.getByCss("[id='" + id + "-reset']", 0, timeout); await resetButton.click(); } // =================================== HELPER =================================== async _verifyTabSwitch(selector) { // two classes required to handle old and new UI5 versions const indicatorClasses = ["sapUxAPAnchorBarButtonSelected", "sapMITBSelected"]; // check for simple tab type const tabElem = await ui5.element.getDisplayed(selector); const tabClassList = await tabElem.getAttribute("class"); if (indicatorClasses.some((indicatorClass) => tabClassList.includes(indicatorClass))) { return true; } // check for multiple value tab type const tabElemTextValue = await ui5.control.getProperty(tabElem, "text"); const tabParentSelector = { elementProperties: { metadata: "sap.m.MenuButton", text: tabElemTextValue, descendentProperties: selector } }; const tabParentElem = await ui5.element.getDisplayed(tabParentSelector, 0, 5000); const tabParentClassList = await tabParentElem.getAttribute("class"); if (indicatorClasses.some((indicatorClass) => tabParentClassList.includes(indicatorClass))) { return true; } else { return false; } } async _selectOption(value) { const textSelector = { elementProperties: { text: value }, ancestorProperties: { metadata: "sap.m.Popover" } }; const titleSelector = { elementProperties: { title: value }, ancestorProperties: { metadata: "sap.m.Popover" } }; const labelSelector = { elementProperties: { label: value }, ancestorProperties: { metadata: "sap.m.Popover" } }; const timeout = 500; const getVisibleSelectorOrFail = async (selector) => { const isVisible = await ui5.element.isVisible(selector, 0, timeout); return isVisible ? selector : Promise.reject(); }; let activeSelector; try { activeSelector = await Promise.any([getVisibleSelectorOrFail(textSelector), getVisibleSelectorOrFail(titleSelector), getVisibleSelectorOrFail(labelSelector)]); } catch (error) { this.ErrorHandler.logException(new Error("No visible elements found.")); } await this.scrollToElement(activeSelector); await this.click(activeSelector); } async _selectMultipleOptions(values) { for (const value of values) { const selector = { elementProperties: { metadata: "sap.m.CheckBox" }, parentProperties: { metadata: "sap.m.StandardListItem", mProperties: { title: value } } }; await this.scrollToElement(selector); await this.click(selector); } await common.userInteraction.pressEscape(); } } exports.UserInteraction = UserInteraction; exports.default = new UserInteraction(); //# sourceMappingURL=userInteraction.js.map