From a60c76fc9643032906a576a1a8248cebfdd053e2 Mon Sep 17 00:00:00 2001 From: Sebastian Mahr Date: Mon, 22 Jan 2024 09:21:25 +0100 Subject: [PATCH] chore: make as Object fluent --- examples/cap-bookshop-wdi5 | 2 +- examples/ui5-ts-app/test/e2e/Input.test.ts | 4 +- src/lib/wdi5-bridge.ts | 153 +++++++-------------- 3 files changed, 55 insertions(+), 104 deletions(-) diff --git a/examples/cap-bookshop-wdi5 b/examples/cap-bookshop-wdi5 index ae62c547..0903c091 160000 --- a/examples/cap-bookshop-wdi5 +++ b/examples/cap-bookshop-wdi5 @@ -1 +1 @@ -Subproject commit ae62c547f6e4e42c93578b204fd3b48d043f68a5 +Subproject commit 0903c091b7702c8c0ce05a807f189c24e43995bb diff --git a/examples/ui5-ts-app/test/e2e/Input.test.ts b/examples/ui5-ts-app/test/e2e/Input.test.ts index ec4590d8..4f71981f 100644 --- a/examples/ui5-ts-app/test/e2e/Input.test.ts +++ b/examples/ui5-ts-app/test/e2e/Input.test.ts @@ -27,9 +27,7 @@ describe("Input", async () => { const control = await browser.asControl(inputSelector) const bindingInfo = await control.getBindingInfo("value") // @ts-expect-error "parts" is not part of the type definition - const parts = await bindingInfo.parts - const partzero = await parts[0] - const path = await partzero.path + const path = await browser.asObject(bindingInfo.getUUID()).parts[0].path expect(path).toEqual("/Customers('TRAIH')/ContactName") }) }) diff --git a/src/lib/wdi5-bridge.ts b/src/lib/wdi5-bridge.ts index 69ad520e..36937da2 100644 --- a/src/lib/wdi5-bridge.ts +++ b/src/lib/wdi5-bridge.ts @@ -425,56 +425,7 @@ export async function _addWdi5Commands(browserInstance: WebdriverIO.Browser) { // the a Proxy and a recursive `handler` function if (!browserInstance.asControl) { browserInstance.asControl = function (ui5ControlSelector) { - const asyncMethods = ["then", "catch", "finally"] - const functionQueue = [] - // we need to do the same operation as in the 'init' of 'wdi5-control.ts' - const logging = ui5ControlSelector?.logging ?? true - function makeFluent(target) { - const promise = Promise.resolve(target) - const handler = { - get(_, prop) { - functionQueue.push(prop) - return asyncMethods.includes(prop) - ? (...boundArgs) => makeFluent(promise[prop](...boundArgs)) - : makeFluent( - promise.then((object) => { - // when object is undefined the previous function call failed - try { - return object[prop] - } catch (error) { - // different node versions return a different `error.message` so we use our own message - if (logging) { - Logger.error(`Cannot read property '${prop}' in the execution queue!`) - } - } - }) - ) - }, - apply(_, thisArg, boundArgs) { - return makeFluent( - // When "targetFunction" is empty we can assume that there are errors in the execution queue - promise.then((targetFunction) => { - if (targetFunction) { - return Reflect.apply(targetFunction, thisArg, boundArgs) - } else { - // a functionQueue without a 'then' can be ignored - // as the original error was already logged - if (functionQueue.includes("then") && logging) { - functionQueue.splice(functionQueue.indexOf("then")) - Logger.error( - `One of the calls in the queue "${functionQueue.join( - "()." - )}()" previously failed!` - ) - } - } - }) - ) - } - } - // eslint-disable-next-line @typescript-eslint/no-empty-function - return new Proxy(function () {}, handler) - } + const makeFluent = createMakeFluent(ui5ControlSelector?.logging) // @ts-ignore return makeFluent(browserInstance._asControl(ui5ControlSelector)) } @@ -482,62 +433,64 @@ export async function _addWdi5Commands(browserInstance: WebdriverIO.Browser) { if (!browserInstance.asObject) { browserInstance.asObject = function (uuid) { - const asyncMethods = ["then", "catch", "finally"] - const functionQueue = [] - // we need to do the same operation as in the 'init' of 'wdi5-control.ts' - const logging = true - function makeFluent(target) { - const promise = Promise.resolve(target) - const handler = { - get(_, prop) { - functionQueue.push(prop) - return asyncMethods.includes(prop) - ? (...boundArgs) => makeFluent(promise[prop](...boundArgs)) - : makeFluent( - promise.then((object) => { - // when object is undefined the previous function call failed - try { - return object[prop] - } catch (error) { - // different node versions return a different `error.message` so we use our own message - if (logging) { - Logger.error(`Cannot read property '${prop}' in the execution queue!`) - } - } - }) - ) - }, - apply(_, thisArg, boundArgs) { - return makeFluent( - // When "targetFunction" is empty we can assume that there are errors in the execution queue - promise.then((targetFunction) => { - if (targetFunction) { - return Reflect.apply(targetFunction, thisArg, boundArgs) - } else { - // a functionQueue without a 'then' can be ignored - // as the original error was already logged - if (functionQueue.includes("then") && logging) { - functionQueue.splice(functionQueue.indexOf("then")) - Logger.error( - `One of the calls in the queue "${functionQueue.join( - "()." - )}()" previously failed!` - ) - } - } - }) - ) - } - } - // eslint-disable-next-line @typescript-eslint/no-empty-function - return new Proxy(function () {}, handler) - } + const makeFluent = createMakeFluent() // @ts-ignore return makeFluent(browserInstance._asObject(uuid)) } } } +export function createMakeFluent(loggin = true) { + const asyncMethods = ["then", "catch", "finally"] + const functionQueue = [] + // we need to do the same operation as in the 'init' of 'wdi5-control.ts' + const logging = loggin + return function makeFluent(target) { + const promise = Promise.resolve(target) + const handler = { + get(_, prop) { + functionQueue.push(prop) + return asyncMethods.includes(prop) + ? (...boundArgs) => makeFluent(promise[prop](...boundArgs)) + : makeFluent( + promise.then((object) => { + // when object is undefined the previous function call failed + try { + return object[prop] + } catch (error) { + // different node versions return a different `error.message` so we use our own message + if (logging) { + Logger.error(`Cannot read property '${prop}' in the execution queue!`) + } + } + }) + ) + }, + apply(_, thisArg, boundArgs) { + return makeFluent( + // When "targetFunction" is empty we can assume that there are errors in the execution queue + promise.then((targetFunction) => { + if (targetFunction) { + return Reflect.apply(targetFunction, thisArg, boundArgs) + } else { + // a functionQueue without a 'then' can be ignored + // as the original error was already logged + if (functionQueue.includes("then") && logging) { + functionQueue.splice(functionQueue.indexOf("then")) + Logger.error( + `One of the calls in the queue "${functionQueue.join("().")}()" previously failed!` + ) + } + } + }) + ) + } + } + // eslint-disable-next-line @typescript-eslint/no-empty-function + return new Proxy(function () {}, handler) + } +} + /** * retrieve a DOM element via UI5 locator * @param {sap.ui.test.RecordReplay.ControlSelector} controlSelector