@sap_oss/wdio-qmate-service
Version:
[](https://api.reuse.software/info/github.com/SAP/wdio-qmate-service)[](http
300 lines • 15.8 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Navigation = void 0;
const verboseLogger_1 = require("../../helper/verboseLogger");
const errorHandler_1 = __importDefault(require("../../helper/errorHandler"));
/**
* @class navigation
* @memberof ui5
*/
class Navigation {
constructor() {
this.vlf = new verboseLogger_1.VerboseLoggerFactory("ui5", "navigation");
this.ErrorHandler = new errorHandler_1.default();
this.errorText = "Navigation failed because page didn't load, possible reasons: " + "Site is down, or you are using a wrong address. For retrying use 'navigateToApplicationAndRetry'.\n";
}
// =================================== MAIN ===================================
/**
* @function navigateToApplication
* @memberOf ui5.navigation
* @description Navigates to the application via the passed intent. The intent will be added to the baseUrl maintained in the config.
* @param {String} intent - The intent of the application.
* @param {Boolean} [preventPopups=false] - Specifies if random popup appearance should be prevented.
* @param {Boolean} [verify=false] - Specifies if the url should be asserted after the navigation.
* @param {Boolean} [refresh=false] - Refresh the page after navigation.
* @example await ui5.navigation.navigateToApplication("PurchaseOrder-manage");
*/
async navigateToApplication(intent, preventPopups = false, verify = false, refresh = true) {
const vl = this.vlf.initLog(this.navigateToApplication);
const baseUrlNormalized = this._normalizeQueryString(browser.config.baseUrl);
const intentNormalized = this._normalizeQueryString(intent);
let queryParams = [];
// Check if intent has query params and extract them from the intent
const intentQueryParams = this._extractQueryParams(intent);
// Check if baseUrl has query params, extract them from the baseUrl and merge them with the existing params
queryParams = queryParams.concat(this._extractQueryParams(browser.config.baseUrl));
// Add prevent popup url params if not already present
if (preventPopups) {
queryParams = queryParams.concat(this._getPreventPopupParams(queryParams));
}
// Construct the url params
let constructedParams = this._constructUrlParams(queryParams);
if (constructedParams !== "")
constructedParams = `?${constructedParams}`;
// Construct the intent params
let constructedIntentParams = this._constructUrlParams(intentQueryParams);
if (constructedIntentParams !== "")
constructedIntentParams = `?${constructedIntentParams}`;
// Construct the final url
const urlWithParams = `${baseUrlNormalized}${constructedParams}#${intentNormalized}${constructedIntentParams}`;
vl.log(`Url with params: ${urlWithParams}`);
try {
await browser.navigateTo(urlWithParams);
const url = await browser.getUrl();
await util.browser.logCurrentUrl();
if (url && !url.includes(intent) && verify) {
new Error("Failed to verify successful navigation.");
}
if (refresh) {
await util.browser.refresh();
}
}
catch (error) {
this.ErrorHandler.logException(error, this.errorText);
}
}
/**
* @function navigateToApplicationAndRetry
* @memberOf ui5.navigation
* @description Navigates to the application via the passed intent, and retries in case it fails.
* @param {String} intent - The intent of the app.
* @param {Boolean} [preventPopups=false] - Specifies if random popup appearance should be prevented. Might not work for specific popups.
* @param {Boolean} [verify=false] - Specifies if the url should be asserted after the navigation.
* @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.navigation.navigateToApplicationAndRetry("PurchaseOrder-manage");
*/
async navigateToApplicationAndRetry(intent, preventPopups = true, verify = true, retries = 3, interval = 5000) {
const vl = this.vlf.initLog(this.navigateToApplicationAndRetry);
await util.function.retry(async (intent, preventPopups) => {
await this.navigateToApplication(intent, preventPopups, verify);
}, [intent, preventPopups, verify], retries, interval, this);
}
/**
* @function navigateToSystemAndApplication
* @memberOf ui5.navigation
* @description Navigates within the passed system to the application via the passed intent.
* @param {String} system - The system url.
* @param {String} intent - The intent of the application.
* @param {Boolean} [closePopups=false] - Specifies if random popups should be closed after the navigation.
* @param {Boolean} [verify=false] - Specifies if the url should be asserted after the navigation.
* @example await ui5.navigation.navigateToSystemAndApplication("yourFioriLaunchpad.domain", "PurchaseOrder-manage");
*/
async navigateToSystemAndApplication(system, intent, closePopups = true, verify = false) {
const vl = this.vlf.initLog(this.navigateToSystemAndApplication);
try {
await browser.navigateTo(`https://${system}/ui#${intent}`);
const url = await browser.getUrl();
await util.browser.logCurrentUrl();
if (url && url.indexOf(intent) === -1 && verify) {
this.ErrorHandler.logException(new Error("For retrying use 'navigateToSystemAndApplicationAndRetry'."));
}
if (closePopups) {
await this.closePopups();
}
}
catch (error) {
this.ErrorHandler.logException(error, this.errorText);
}
}
/**
* @function navigateToSystemAndApplicationAndRetry
* @memberOf ui5.navigation
* @description Navigates within the passed system to the application via the passed intent, and retries in case it fails.
* @param {String} system - The system url.
* @param {String} intent - The intent of the application.
* @param {Boolean} [closePopups=false] - Specifies if random popups should be closed after the navigation.
* @param {Boolean} [verify=false] - Specifies if the url should be asserted after the navigation.
* @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.navigation.navigateToSystemAndApplicationAndRetry("yourFioriLaunchpad.domain", "PurchaseOrder-manage");
*/
async navigateToSystemAndApplicationAndRetry(system, intent, closePopups = true, verify = true, retries = 3, interval = 5000) {
const vl = this.vlf.initLog(this.navigateToSystemAndApplicationAndRetry);
await util.function.retry(async (system, intent, closePopups) => {
await this.navigateToSystemAndApplication(system, intent, closePopups, verify);
}, [system, intent, closePopups, verify], retries, interval, this);
}
/**
* @function navigateToApplicationWithQueryParams
* @memberOf ui5.navigation
* @description Navigates to the application with the passed queryParams via the passed intent.
* @param {String} intent - The intent of the app.
* @param {String} queryParams - [OPTIONAL] Add url query params.
* @param {Boolean} [preventPopups=false] - Specifies if random popup appearance should be prevented.
* @param {Boolean} [verify=false] - Specifies if the url should be asserted after the navigation.
* @example const intent = "PurchaseOrder-manage"
* const queryParams = "?sap-language=EN&responderOn=true";
* await ui5.navigation.navigateToApplicationWithQueryParams(intent, queryParams);
*/
async navigateToApplicationWithQueryParams(intent, queryParams = "", closePopups = true, verify = false) {
const vl = this.vlf.initLog(this.navigateToApplicationWithQueryParams);
let url;
try {
let parsedQueryParams = "";
if (queryParams) {
if (queryParams.startsWith("?")) {
parsedQueryParams = queryParams;
}
else {
parsedQueryParams = `?${queryParams}`;
}
}
await browser.url(`${browser.config.baseUrl}${parsedQueryParams}#${intent}`);
url = await browser.getUrl();
await util.browser.logCurrentUrl();
if (url && url.indexOf(intent) === -1 && verify) {
this.ErrorHandler.logException(new Error("For retrying use 'navigateToSystemAndApplicationAndRetry'."));
}
if (closePopups) {
await ui5.navigation.closePopups();
}
await browser.refresh();
}
catch (error) {
this.ErrorHandler.logException(error, this.errorText);
}
}
/**
* @function navigateToApplicationWithQueryParamsAndRetry
* @memberOf ui5.navigation
* @description Navigates to the application via the passed intent, and retries in case it fails.
* @param {String} intent - The intent of the app.
* @param {String} queryParams - [OPTIONAL] Add url query params.
* @param {Boolean} [preventPopups=false] - Specifies if random popup appearance should be prevented.
* @param {Boolean} [verify=false] - Specifies if the url should be asserted after the navigation.
* @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 const intent = "PurchaseOrder-manage"
* const queryParams = "?sap-language=EN&responderOn=true";
* await ui5.navigation.navigateToApplicationWithQueryParamsAndRetry(intent, queryParams);
*/
async navigateToApplicationWithQueryParamsAndRetry(intent, queryParams, closePopups = true, verify = true, retries = 3, interval = 5000) {
const vl = this.vlf.initLog(this.navigateToApplicationWithQueryParamsAndRetry);
await util.function.retry(async (intent, queryParams, closePopups, verify) => {
await this.navigateToApplicationWithQueryParams(intent, queryParams, closePopups, verify);
}, [intent, queryParams, closePopups, verify], retries, interval, this);
}
// =================================== POPUPS ===================================
/**
* @function closePopups
* @memberOf ui5.navigation
* @description Closes all popups if they occur after navigating to a specific page.
* @param {Number} [timeout=30000] - The timeout to wait.
* @example await ui5.navigation.closePopups();
*/
async closePopups(timeout = 30000) {
const vl = this.vlf.initLog(this.closePopups);
const popups = [
{
name: "Help Dialog",
selector: ".help4-wrapper button"
},
{
name: "SAML Dialog",
selector: "BUTTON[class='sapMBtnBase sapMBtn sapMDialogEndButton sapMBarChild']"
}
];
const popupHandlers = popups.map((popup) => this._closePopup(popup, timeout));
return Promise.all(popupHandlers);
}
// =================================== ASSERTION ===================================
/**
* @function expectUnsupportedNavigationPopup
* @memberOf ui5.navigation
* @description Expects navigation to an app that is not supported.
* This can be the case for Mocked tests when the application does not exist or when the app is not included in a role.
* @param {String} navigationTarget - The selector describing the element.
* @example await ui5.navigation.expectUnsupportedNavigationPopup("#SupplierInvoice-display?FiscalYear=1234&SupplierInvoice=1234567890");
*/
async expectUnsupportedNavigationPopup(navigationTarget) {
const vl = this.vlf.initLog(this.expectUnsupportedNavigationPopup);
const unsupportedNavigationPopup = {
elementProperties: {
metadata: "sap.m.Dialog",
type: "Message",
state: "Error"
}
};
await ui5.assertion.expectToBeVisible(unsupportedNavigationPopup);
const moreDetailsButton = {
elementProperties: {
metadata: "sap.m.Link",
ancestor: unsupportedNavigationPopup
}
};
await ui5.userInteraction.click(moreDetailsButton);
const selector = {
elementProperties: {
metadata: "sap.m.FormattedText",
ancestorProperties: unsupportedNavigationPopup
}
};
const detailsTextElement = await ui5.element.getDisplayed(selector);
const dataHtmlText = await detailsTextElement.getAttribute("data-htmltext");
const stringExists = await dataHtmlText.includes(navigationTarget.replace(/&/g, "&"));
return common.assertion.expectTrue(stringExists);
}
// =================================== HELPER ===================================
_extractQueryParams(input) {
const queryParams = [];
const queryParts = input.split("?");
if (queryParts.length > 1) {
queryParams.push(...this._mapQueryParams(queryParts[1]));
}
return queryParams;
}
_normalizeQueryString(input) {
const queryParts = input.split("?");
return queryParts[0];
}
_constructUrlParams(queryParams) {
return queryParams.map((param) => `${param.key}=${param.value}`).join("&");
}
_getPreventPopupParams(queryParams) {
const combinedQueryParams = [];
const READ_CATALOG_PARAM = "help-readCatalog";
const STATE_UACP_PARAM = "help-stateUACP";
const hasReadCatalog = queryParams.some((param) => param.key === READ_CATALOG_PARAM);
const hasStateUACP = queryParams.some((param) => param.key === STATE_UACP_PARAM);
if (!hasReadCatalog) {
combinedQueryParams.push({ key: READ_CATALOG_PARAM, value: "false" });
}
if (!hasStateUACP) {
combinedQueryParams.push({ key: STATE_UACP_PARAM, value: "PRODUCTION" });
}
return combinedQueryParams;
}
_mapQueryParams(params) {
return params.split("&").map((param) => {
const [key, value] = param.split("=");
return { key, value };
});
}
async _closePopup(popup, timeout = 30000) {
try {
const elem = await nonUi5.element.getByCss(popup.selector, 0, timeout);
await nonUi5.userInteraction.click(elem);
util.console.log(`${popup.name} was closed.`);
}
catch (error) {
util.console.log(`${popup.name} not found.`);
}
}
}
exports.Navigation = Navigation;
exports.default = new Navigation();
//# sourceMappingURL=navigation.js.map