diff --git a/client-side-js/_checkForUI5Ready.cjs b/client-side-js/_checkForUI5Ready.cjs index eb9a7e09..c9d3e56e 100644 --- a/client-side-js/_checkForUI5Ready.cjs +++ b/client-side-js/_checkForUI5Ready.cjs @@ -1,7 +1,7 @@ async function clientSide__checkForUI5Ready(browserInstance) { return await browserInstance.execute(async () => { try { - await window.wdi5.waitForUI5(window.wdi5.waitForUI5Options) + await window.bridge.waitForUI5(window.wdi5.waitForUI5Options) } catch (error) { return window.wdi5.errorHandling(error) } diff --git a/client-side-js/allControls.cjs b/client-side-js/allControls.cjs index 17077f08..dbc07e37 100644 --- a/client-side-js/allControls.cjs +++ b/client-side-js/allControls.cjs @@ -7,14 +7,14 @@ async function clientSide_allControls(controlSelector, browserInstance) { } try { - await window.wdi5.waitForUI5(waitForUI5Options) + await window.bridge.waitForUI5(waitForUI5Options) } catch (error) { return window.wdi5.errorHandling(error) } window.wdi5.Log.info("[browser wdi5] locating " + JSON.stringify(controlSelector)) controlSelector.selector = window.wdi5.createMatcher(controlSelector.selector) - let domElements; + let domElements try { domElements = await window.bridge.findAllDOMElementsByControlSelector(controlSelector) diff --git a/client-side-js/executeControlMethod.cjs b/client-side-js/executeControlMethod.cjs index 5ee4d11e..1ff940fd 100644 --- a/client-side-js/executeControlMethod.cjs +++ b/client-side-js/executeControlMethod.cjs @@ -13,118 +13,112 @@ if (global.browser) { async function executeControlMethod(webElement, methodName, browserInstance, args) { return await browserInstance.execute( async (webElement, methodName, args) => { - return new Promise(async (resolve, reject) => { - await window.wdi5.waitForUI5( - window.wdi5.waitForUI5Options, - () => { - // DOM to UI5 - const oControl = window.wdi5.getUI5CtlForWebObj(webElement) + await window.bridge.waitForUI5(window.wdi5.waitForUI5Options) + // window.wdi5.errorHandling.bind(this, null, reject) - // execute the function - let result = oControl[methodName].apply(oControl, args) - const metadata = oControl.getMetadata() + // DOM to UI5 + const oControl = window.wdi5.getUI5CtlForWebObj(webElement) - if (Array.isArray(result)) { - if (result.length === 0) { - resolve({ status: 0, result: result, returnType: "empty" }) - } else if (result[0]?.getParent) { - // expect the method call delivers non-primitive results (like getId()) - // but delivers a complex/structured type - // -> currenlty, only getAggregation(...) is supported - // read classname eg. sap.m.ComboBox - controlType = oControl.getMetadata()._sClassName + // execute the function + let result = oControl[methodName].apply(oControl, args) + const metadata = oControl.getMetadata() - result = window.wdi5.createControlIdMap(result, controlType) - resolve({ status: 0, result: result, returnType: "aggregation" }) - } else { - resolve({ status: 0, result: result, returnType: "result" }) - } - } else { - // ui5 api .focus() doesn't have return value - if (methodName === "focus" && result === undefined) { - resolve({ - status: 0, - result: `called focus() on wdi5 representation of a ${metadata.getElementName()}`, - returnType: "element" - }) - } else if (methodName === "exec" && result && result.status > 0) { - resolve({ - status: result.status, - message: result.message - }) - } else if (result === undefined || result === null) { - resolve({ - status: 1, - result: `function ${methodName} does not exist on control ${metadata.getElementName()}!`, - returnType: "none" - }) - } else { - if (window.wdi5.isPrimitive(result)) { - resolve({ status: 0, result: result, returnType: "result" }) - } else if ( - // we have an object that is not a UI5 control - typeof result === "object" && - result !== null && - !(result instanceof sap.ui.core.Control) && - !(result instanceof sap.ui.core.Item) - ) { - // save before manipulate - const uuid = window.wdi5.saveObject(result) + if (Array.isArray(result)) { + if (result.length === 0) { + return { status: 0, result: result, returnType: "empty" } + } else if (result[0]?.getParent) { + // expect the method call delivers non-primitive results (like getId()) + // but delivers a complex/structured type + // -> currenlty, only getAggregation(...) is supported + // read classname eg. sap.m.ComboBox + controlType = oControl.getMetadata()._sClassName + + result = window.wdi5.createControlIdMap(result, controlType) + return { status: 0, result: result, returnType: "aggregation" } + } else { + return { status: 0, result: result, returnType: "result" } + } + } else { + // ui5 api .focus() doesn't have return value + if (methodName === "focus" && result === undefined) { + return { + status: 0, + result: `called focus() on wdi5 representation of a ${metadata.getElementName()}`, + returnType: "element" + } + } else if (methodName === "exec" && result && result.status > 0) { + return { + status: result.status, + message: result.message + } + } else if (result === undefined || result === null) { + return { + status: 1, + result: `function ${methodName} does not exist on control ${metadata.getElementName()}!`, + returnType: "none" + } + } else { + if (window.wdi5.isPrimitive(result)) { + return { status: 0, result: result, returnType: "result" } + } else if ( + // we have an object that is not a UI5 control + typeof result === "object" && + result !== null && + !(result instanceof sap.ui.core.Control) && + !(result instanceof sap.ui.core.Item) + ) { + // save before manipulate + const uuid = window.wdi5.saveObject(result) - // FIXME: extract, collapse and remove cylic in 1 step - // extract the methods first - const aProtoFunctions = window.wdi5.retrieveControlMethods(result, true) + // FIXME: extract, collapse and remove cylic in 1 step + // extract the methods first + const aProtoFunctions = window.wdi5.retrieveControlMethods(result, true) - // flatten the prototype so we have all funcs available - const collapsed = window.wdi5.collapseObject(result) - // exclude cyclic references - const collapsedAndNonCyclic = JSON.parse( - JSON.stringify(collapsed, window.wdi5.getCircularReplacer()) - ) - // remove all empty Array elements, inlcuding private keys (starting with "_") - const semanticCleanedElements = - window.wdi5.removeEmptyElements(collapsedAndNonCyclic) + // flatten the prototype so we have all funcs available + const collapsed = window.wdi5.collapseObject(result) + // exclude cyclic references + const collapsedAndNonCyclic = JSON.parse( + JSON.stringify(collapsed, window.wdi5.getCircularReplacer()) + ) + // remove all empty Array elements, inlcuding private keys (starting with "_") + const semanticCleanedElements = window.wdi5.removeEmptyElements(collapsedAndNonCyclic) - resolve({ - status: 0, - object: semanticCleanedElements, - returnType: "object", - aProtoFunctions: aProtoFunctions, - uuid: uuid, - nonCircularResultObject: semanticCleanedElements - }) - } else if ( - typeof result === "object" && - result !== null && - // wdi5 returns a wdi5 control if the UI5 api return its control - // allows method chaining - !(result instanceof sap.ui.base.Object) - ) { - resolve({ - status: 2, - returnType: "unknown" - }) - } else { - // we got ourselves a regular UI5 control - // check that we're not working against ourselves :) - if (result && result.getId && oControl.getId() !== result.getId()) { - // ui5 function like get parent might return another ui5 control -> return it to check with this wdi5 instance - result = window.wdi5.createControlId(result) - resolve({ status: 0, result: result, returnType: "newElement" }) - } else { - resolve({ - status: 0, - result: `instance of wdi5 representation of a ${metadata.getElementName()}`, - returnType: "element" - }) - } - } + return { + status: 0, + object: semanticCleanedElements, + returnType: "object", + aProtoFunctions: aProtoFunctions, + uuid: uuid, + nonCircularResultObject: semanticCleanedElements + } + } else if ( + typeof result === "object" && + result !== null && + // wdi5 returns a wdi5 control if the UI5 api return its control + // allows method chaining + !(result instanceof sap.ui.base.Object) + ) { + return { + status: 2, + returnType: "unknown" + } + } else { + // we got ourselves a regular UI5 control + // check that we're not working against ourselves :) + if (result && result.getId && oControl.getId() !== result.getId()) { + // ui5 function like get parent might return another ui5 control -> return it to check with this wdi5 instance + result = window.wdi5.createControlId(result) + return { status: 0, result: result, returnType: "newElement" } + } else { + return { + status: 0, + result: `instance of wdi5 representation of a ${metadata.getElementName()}`, + returnType: "element" } } - }, - window.wdi5.errorHandling.bind(this, null, reject) - ) - }) + } + } + } }, webElement, methodName, diff --git a/client-side-js/executeObjectMethod.cjs b/client-side-js/executeObjectMethod.cjs index 6b9bf9f5..1f0cc22d 100644 --- a/client-side-js/executeObjectMethod.cjs +++ b/client-side-js/executeObjectMethod.cjs @@ -2,7 +2,7 @@ async function clientSide_executeObjectMethod(uuid, methodName, args) { return await browser.execute( async (uuid, methodName, args) => { return new Promise(async (resolve, reject) => { - await window.wdi5.waitForUI5( + await window.bridge.waitForUI5( window.wdi5.waitForUI5Options, // this callback is denoted "async" even though it is truely not // but what other way to `await` a potentially async UI5 managed object fn in here? diff --git a/client-side-js/fireEvent.cjs b/client-side-js/fireEvent.cjs index 357473b7..9f472dd8 100644 --- a/client-side-js/fireEvent.cjs +++ b/client-side-js/fireEvent.cjs @@ -4,7 +4,7 @@ async function clientSide_fireEvent(webElement, eventName, oOptions, browserInst return await browserInstance.execute( async (webElement, eventName, oOptions) => { try { - await window.wdi5.waitForUI5(window.wdi5.waitForUI5Options) + await window.bridge.waitForUI5(window.wdi5.waitForUI5Options) } catch (error) { return window.wdi5.errorHandling(error) } diff --git a/client-side-js/getControl.cjs b/client-side-js/getControl.cjs index 25bbf80d..b488915e 100644 --- a/client-side-js/getControl.cjs +++ b/client-side-js/getControl.cjs @@ -7,7 +7,7 @@ async function clientSide_getControl(controlSelector, browserInstance) { } try { - await window.wdi5.waitForUI5(waitForUI5Options) + await window.bridge.waitForUI5(waitForUI5Options) } catch (error) { return window.wdi5.errorHandling(error) } diff --git a/client-side-js/getObject.cjs b/client-side-js/getObject.cjs index 9fa199a6..f4fe1ca1 100644 --- a/client-side-js/getObject.cjs +++ b/client-side-js/getObject.cjs @@ -3,7 +3,7 @@ async function clientSide_getObject(uuid) { const waitForUI5Options = Object.assign({}, window.wdi5.waitForUI5Options) try { - await window.wdi5.waitForUI5(waitForUI5Options) + await window.bridge.waitForUI5(waitForUI5Options) } catch (error) { return window.wdi5.errorHandling(error) } diff --git a/client-side-js/getSelectorForElement.cjs b/client-side-js/getSelectorForElement.cjs index 1fb407ad..bb9bd30b 100644 --- a/client-side-js/getSelectorForElement.cjs +++ b/client-side-js/getSelectorForElement.cjs @@ -2,7 +2,7 @@ async function clientSide_getSelectorForElement(oOptions, browserInstance) { return await browserInstance.execute(async (oOptions) => { try { - await window.wdi5.waitForUI5(window.wdi5.waitForUI5Options) + await window.bridge.waitForUI5(window.wdi5.waitForUI5Options) } catch (error) { return window.wdi5.errorHandling(error) } @@ -10,8 +10,7 @@ async function clientSide_getSelectorForElement(oOptions, browserInstance) { window.wdi5.Log.info("[browser wdi5] locating domElement") let controlSelector try { - controlSelector = await window.bridge - .findControlSelectorByDOMElement(oOptions) + controlSelector = await window.bridge.findControlSelectorByDOMElement(oOptions) } catch (error) { return window.wdi5.errorHandling(error) } diff --git a/client-side-js/interactWithControl.cjs b/client-side-js/interactWithControl.cjs index 44e0a8cd..c1def0e3 100644 --- a/client-side-js/interactWithControl.cjs +++ b/client-side-js/interactWithControl.cjs @@ -2,7 +2,7 @@ async function clientSide_interactWithControl(oOptions, browserInstance) { browserInstance = await Promise.resolve(browserInstance) return await browserInstance.execute(async (oOptions) => { try { - await window.wdi5.waitForUI5(window.wdi5.waitForUI5Options) + await window.bridge.waitForUI5(window.wdi5.waitForUI5Options) } catch (error) { return window.wdi5.errorHandling(error) } diff --git a/client-side-js/testLibrary.cjs b/client-side-js/testLibrary.cjs index 9d678fe0..da057214 100644 --- a/client-side-js/testLibrary.cjs +++ b/client-side-js/testLibrary.cjs @@ -1,7 +1,7 @@ async function initOPA(pageObjectConfig, browserInstance) { return await browserInstance.execute(async (pageObjectConfig) => { try { - await window.wdi5.waitForUI5(window.wdi5.waitForUI5Options) + await window.bridge.waitForUI5(window.wdi5.waitForUI5Options) const pageConfig = {} Object.keys(pageObjectConfig).map((pageKey) => { @@ -31,21 +31,17 @@ async function initOPA(pageObjectConfig, browserInstance) { // different error handling for the test library return ["error", error.toString()] } - - - - }, pageObjectConfig) } async function emptyQueue(browserInstance) { return await browserInstance.execute(async () => { try { debugger - await window.wdi5.waitForUI5(window.wdi5.waitForUI5Options) + await window.bridge.waitForUI5(window.wdi5.waitForUI5Options) await sap.ui.test.Opa.emptyQueue() const feLogs = window.fe_bridge.Log window.fe_bridge.Log = [] - return ({ type: "success", feLogs: feLogs }) + return { type: "success", feLogs: feLogs } } catch (error) { return { type: "error", @@ -61,7 +57,7 @@ async function emptyQueue(browserInstance) { async function addToQueue(methodCalls, browserInstance) { return await browserInstance.execute(async (methodCalls) => { try { - await window.wdi5.waitForUI5(window.wdi5.waitForUI5Options) + await window.bridge.waitForUI5(window.wdi5.waitForUI5Options) for (const methodCall of methodCalls) { let scope diff --git a/examples/ui5-js-app/e2e-test-config/wdio-webserver.conf.js b/examples/ui5-js-app/e2e-test-config/wdio-webserver.conf.js index 34c1ead0..2f0fadc1 100644 --- a/examples/ui5-js-app/e2e-test-config/wdio-webserver.conf.js +++ b/examples/ui5-js-app/e2e-test-config/wdio-webserver.conf.js @@ -3,7 +3,7 @@ const { baseConfig } = require("./wdio.base.conf") const merge = require("deepmerge") const _config = { - specs: [join("..", "webapp", "test", "e2e", "**/*.test.js")], + specs: [join("..", "webapp", "test", "e2e", "**/basic.test.js")], exclude: [ join("..", "webapp", "test", "e2e", "ui5-late.test.js"), join("..", "webapp", "test", "e2e", "multiremote.test.js") diff --git a/examples/ui5-js-app/e2e-test-config/wdio.base.conf.js b/examples/ui5-js-app/e2e-test-config/wdio.base.conf.js index 684619cd..672bb2b4 100644 --- a/examples/ui5-js-app/e2e-test-config/wdio.base.conf.js +++ b/examples/ui5-js-app/e2e-test-config/wdio.base.conf.js @@ -12,7 +12,7 @@ exports.baseConfig = { maxInstances: 4, browserName: "chrome", acceptInsecureCerts: true, - // "wdio:enforceWebDriverClassic": true, + "wdio:enforceWebDriverClassic": true, "goog:chromeOptions": { args: process.argv.indexOf("--headless") > -1