Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

array properties are treated as aggregations and fail to return results #172

Closed
edvardas-kireilis opened this issue Mar 8, 2022 · 3 comments

Comments

@edvardas-kireilis
Copy link
Contributor

edvardas-kireilis commented Mar 8, 2022

Describe the bug
Calling a get method which returns an array results in timeout. Debugging of _ControlFinder.js and puppeteer code reveals that if method results is an array - it is treaded as a result of aggregation which is not correct in sap.m.MultiComboBox property selectedKeys.
This limitation makes it impossible to retrieve any property which contains an array.

To Reproduce
Try to retrieve selectedKeys property from sap.m.MultiComboBox control.
api url: (https://sapui5.hana.ondemand.com/sdk/#/api/sap.m.MultiComboBox)

I used this code:

    const control = await browser.asControl({
      forceSelect: true,
      selector: {
        id: 'kindFilterCombo',
        controlType: 'sap.m.MultiComboBox',
        viewName: viewName,
        interaction: 'root'
      }
    })

    const keys = await control.getSelectedKeys()

Expected behavior
Selected key list array (array of strings) should be returned.

The code should look into control aggregation list to validate if method returns aggregation and not assume that array is always means aggregation results.

Logs/Console Output

[0-0] 2022-03-08T00:54:40.850Z INFO devtools: COMMAND findElement("css selector", "#__xmlview0--kindFilterCombo")
[0-0] 2022-03-08T00:54:40.857Z INFO devtools: RESULT { 'element-6066-11e4-a52e-4f735466cecf': 'ELEMENT-14' }
[0-0] 2022-03-08T00:54:40.866Z INFO devtools: COMMAND executeAsyncScript("return ((webElement, methodName, args, done) => {
[0-0]                 window.bridge.waitForUI5(window.wdi5.waitForUI5Options).then(() => {
[0-0]                     // DOM to UI5
[0-0]                     const oControl = window.wdi5.getUI5CtlForWebObj(webElement);
[0-0]                     // execute the function
[0-0]                     let result = oControl[methodName].apply(oControl, args);
[0-0]                     const metadata = oControl.getMetadata();
[0-0]                     if (Array.isArray(result)) {
[0-0]                         // expect the method call delivers non-primitive results (like getId())
[0-0]                         // but delivers a complex/structured type
[0-0]                         // -> currenlty, only getAggregation(...) is supported
[0-0]                         result = window.wdi5.createControlIdMap(result);
[0-0]                         done(['success', result, 'aggregation']);
[0-0]                     } else {
[0-0]                         // ui5 api <control>.focus() doesn't have return value
[0-0]                         if (methodName === 'focus' && result === undefined) {
[0-0]                             done([
[0-0]                                 'success',
[0-0]                                 `called focus() on wdi5 representation of a ${metadata.getElementName()}`,
[0-0]                                 'element'
[0-0]                             ]);
[0-0]                         } else if (result === undefined || result === null) {
[0-0]                             done([
[0-0]                                 'error',
[0-0]                                 `function ${methodName} does not exist on control ${metadata.getElementName()}!`,
[0-0]                                 'none'
[0-0]                             ]);
[0-0]                         } else {
[0-0]                             // result mus be a primitive
[0-0]                             if (window.wdi5.isPrimitive(result)) {
[0-0]                                 // getter
[0-0]                                 done(['success', result, 'result']);
[0-0]                             } else {
[0-0]                                 // object, replacer function
[0-0]                                 // TODO: create usefull content from result
[0-0]                                 // result = JSON.stringify(result, window.wdi5.circularReplacer());
[0-0] 
[0-0]                                 // check if of control to verify if the method result is a different control
[0-0]                                 if (result && result.getId && oControl.getId() !== result.getId()) {
[0-0]                                     // ui5 function like get parent might return another ui5 control -> return it to check with this wdi5 instance
[0-0]                                     result = window.wdi5.createControlId(result);
[0-0]                                     done(['success', result, 'newElement']);
[0-0]                                 } else {
[0-0]                                     done([
[0-0]                                         'success',
[0-0]                                         `instance of wdi5 representation of a ${metadata.getElementName()}`,
[0-0]                                         'element'
[0-0]                                     ]);
[0-0]                                 }
[0-0]                             }
[0-0]                         }
[0-0]                     }
[0-0]                 });
[0-0]             }).apply(null, arguments)", <object>)
[0-0] 2022-03-08T00:54:42.107Z INFO devtools: RESULT [ 'success', [], 'aggregation' ]

Runtime Env (please complete the following information):

  • wdi5/wdio-ui5-service-version: [e.g. 0.8.2]
  • UI5 version: 1.98.0
  • wdio-version: 7.16.16
  • node-version: v16.13.0
  • OS: [macOS]
  • Browser - chrome 99.0.4844.51
@vobu
Copy link
Contributor

vobu commented Mar 8, 2022

thanks for providing mucho debug and context info here 👍

couple of things:

so my suggestion is: please look into the PR #170 and check whether that would solve your case.
and please also check #121 for possible duplicate.

thanks!

@edvardas-kireilis
Copy link
Contributor Author

Thanks for such a fast reply.
I have looked in wrong location for ui5 version. We use 1.98.0 at the moment.

The change you suggested (170) should work in my case since getSelectedKeys returns array of strings. But this change will cause other issues in future for cases with properties containing object array.

May I suggest doing a check of result first element to see if it has a getParent() method which points to oControl from which the list was retrieved? That way we would know that at least first element is a child or control and assume that method is returning aggregation.
Another way to check if method returns property could be to use getProperty('propertyName') method and check if it returns a value or an error. That way we would always know when we return a property value.

thanks for providing mucho debug and context info here 👍

couple of things:

so my suggestion is: please look into the PR #170 and check whether that would solve your case. and please also check #121 for possible duplicate.

thanks!

@vobu
Copy link
Contributor

vobu commented Mar 8, 2022

nice idea! Would you mind giving it a shot together with @ph-alsvik in #170? He could allow for contributor rights to his fork or you could PR his fork.
In case this gets too cumbersome - let me know and I'll put the PR #170 on a dedicated branch in the wdi5 repo itself and give you two access rights.
Also, I wouldn't mind hopping on a shared coding session (https://code.visualstudio.com/learn/collaboration/live-share) if you feel this would help 😸

@vobu vobu closed this as completed in b7a2789 Mar 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants