@sap_oss/wdio-qmate-service
Version:
[](https://api.reuse.software/info/github.com/SAP/wdio-qmate-service)[](http
760 lines • 41.2 kB
JavaScript
"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