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

Expose type of WDI5Control to consumers #544

Closed
LukasHeimann opened this issue Sep 19, 2023 · 4 comments · Fixed by #547
Closed

Expose type of WDI5Control to consumers #544

LukasHeimann opened this issue Sep 19, 2023 · 4 comments · Fixed by #547

Comments

@LukasHeimann
Copy link
Contributor

LukasHeimann commented Sep 19, 2023

Describe the bug
Hi everyone,

I'm currently updating wdi5 to v2 in my project, and I'm using TypeScript. However, I noticed an issue with the newly enforced restrictions on importing things: https://github.com/ui5-community/wdi5/blob/main/package.json#L20-L23

In my project, I slightly extend the browser object and was, in the past, able to reuse the types that wdi5 offered. For that, I just had an ambient type definition (global.d.ts) in which I imported the library types:

type WDI5Selector = import("wdio-ui5-service/dist/types/wdi5.types").wdi5Selector;
type WDI5Control = import("wdio-ui5-service/dist/lib/wdi5-control").WDI5Control;

With the update, I'm now restricted to importing only what is explicitly defined in the package.json -- which is valid and good. I still get access to the wdi5Selector type, as that is exported by index.ts: https://github.com/ui5-community/wdi5/blob/main/src/index.ts#L11. WDI5Control, however, is not, meaning I am not able to use the type.

You don't even need an esoteric use case for that, perhaps you only want to have your test types a bit better under control:

// I don't want myControl to have all UI5 types of https://github.com/ui5-community/wdi5/blob/main/src/types/browser-commands.ts#L18
const myControl: WDI5Control = myControl: browser.asControl({...});
// not allowed to use UI5-Control-specific methods on myControl, just the wdi5 basics

I tried to work around this by trying to use ReturnType<WebdriverIO.Browser.asControl>, but wasn't getting anywhere (and I would have had to remove the Promise and the & T as well...

It would be better if I could just import the type directly. Please consider it as a (type) export to your index.ts.

Thank you very much for your support!
Kind regards
Lukas

To Reproduce
Start a project with wdi5 and TypeScript. Try to import WDI5Control (as a type).

Expected behavior
Be able to import WDI5Control as a type. I don't need to be able to import WDI5Control as value, because I shouldn't be able to instantiate it myself (this should be done by the framework). But as I am supposed to work with objects of type WDI5Control in my code, I should also be able to import the type.

Runtime Env (please complete the following information):

  • wdi5/wdio-ui5-service-version: 2.0.0
  • UI5 version: 1.118.0
  • wdio-version (output of wdio --version): 8.16.11
  • node-version (output of node --version): v18.17.1
  • OS: Win 11
  • Browser + Version: n/a

Additional:

  • Typescript 5.2.2
  • package.json: "type": "module" (not commonjs, as that doesn't fly with wdio 8)
  • tsconfig:
    {
      "compilerOptions": {
        "moduleResolution": "Node16",
        "target": "es2022",
        "module": "Node16",
        "strict": true,
        "types": [
          "node",
          "@sapui5/types",
          "@wdio/globals/types",
          "expect-webdriverio",
          "@wdio/mocha-framework",
          "wdio-ui5-service"
        ],
        "skipLibCheck": true
      }
    }
@vobu
Copy link

vobu commented Sep 22, 2023

Hi Lukas, totally get your point, it's actually almost a bug 😁
Would you mind slapping in additional exports into https://github.com/ui5-community/wdi5/blob/main/src/types/wdi5.types.ts for WDI5Control in a PR? That would be awesome ☺️

Generally speaking, we're unfortunately not in a good shape yet with types in wdi5;
specifically for UI5 controls retrieved from the browser scope at test-time: they require dynamic typing at runtime, which we simply haven't figured out properly yet.
Ideally, the returned object in Node.js-scope should be of the same type the browser control is.

const control = await browser.asControl($sap_m_Button)
// control should be of type sap.m.Button without having to cast it

Probably https://www.typescriptlang.org/docs/handbook/2/typeof-types.html might be worth a shot, but time...
You don't happen to have some TS type wizardry 🧙 at hand, do you...?!?

@LukasHeimann
Copy link
Contributor Author

I'll have a look at exporting it. WDI5 Control actually is over here: https://github.com/ui5-community/wdi5/blob/main/src/lib/wdi5-control.ts, not in the types. But I could have a look at building a proxy with just the type of it in the types file, if that is what you are looking for :)

@LukasHeimann
Copy link
Contributor Author

The main problem is that you'll need to tie the runtime back to the design time. The only idea I'd have for that would be using the element type given in the selector. But I guess you'd need to have an exhaustive map of types for that to work (and thus that map would be non-extensible):

import Input from "sap/m/Input";
import Text from "sap/m/Text";
import Control from "sap/ui/core/Control";

type TypeMap = {
  "sap.m.Text": Text,
  "sap.m.Input": Input,
  "": Control,
};

function getInstanceOfByName<Name extends keyof TypeMap>(name: Name): TypeMap[Name] {
  return undefined as unknown as TypeMap[Name]; // dummy
}

const text = getInstanceOfByName("sap.m.Text");
const input = getInstanceOfByName("sap.m.Input");
const anythingElse = getInstanceOfByName("");

@LukasHeimann
Copy link
Contributor Author

I've created #547 to add the type export.

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

Successfully merging a pull request may close this issue.

2 participants