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

300 lines 15.8 kB
"use strict"; 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