Closed xiaoyurenqa closed 6 months ago
and it seems like there is no way to declare the browser's type since it's not exposed.
I think you can directly use WebdriverIO.Browser
(playground link) but I think it is not able to automatically detect methods supported by the type (WebdriverIO.Browser).
is not true since they are exactly the same type
import type { browser } from "@wdio/globals";
const someBrowser: typeof browser = {} as any;
someBrowser.findElement
// ^?
const otherBrowser: WebdriverIO.Browser = {} as any
// ^?
otherBrowser.findElement
I personally do not like relying on TypeScript namespace but WebdriverIO
namespace is used in many places already.
Note that unrelated to the original issue, but having import
ing @wdio/globals
introduces several global variables in type level such as driver
and expect
but in runtime, there is no such variables. You can see this in the playground, where there is no type error for global driver
variable but if you run the script, it fails since there is no driver
. I am not sure whether it's good to use @wdio/globals
in standalone mode
You can import the WebdriverIO.Browser
or WebdriverIO.Element
type we define within the WebdriverIO
namespace via:
import type { Browser, Element } from 'webdriverio'
Do you have a suggestion where we should document this better?
UPDATE: this is not a recommended way of using these types which is why they are deprecated.
@christian-bromann Both Browser
and Element
types from webdriverio
is marked as @deprecated
(Playground, code) and it looks like this decision was done in https://github.com/webdriverio/webdriverio/pull/11590
IMHO, I think we should do the opposite. We can stop relying on TypeScript namespace and instead we can rely on TypeScript modules. TypeScript namespace is unnecessarily global. I know this is an edge case but TypeScript modules work better for any situations such as having different versions of webdriverio
package via npm alias:
import type { Browser as Browser1, Element as Element1 } from 'webdriverio@8.1'
import type { Browser as Browser2, Element as Element 1} from 'webdriverio@8.2'
Just curious, is there strong reason to prefer TypeScript namespace? Is this due to historical reasons?
UPDATE: I just found the reason described in https://github.com/webdriverio/webdriverio/issues/11055#issuecomment-1698164693, we want to use TypeScript namespace so that libraries can extend... hmmm I am curious whether there are better alternative for "extending types" pattern
Ah, thanks for recalling my memory on this. I am not aware of any way that allows to dynamically extend TypeScript interfaces. Currently we allow users to add custom commands to the Browser
and Element
and have this being reflected in the types which is pretty neat. Sure users could create their own Browser interface and extend from it but this approach feels easier to maintain.
Furthermore we want to provide type support for wdio.conf.ts
files, especially the defined service and reporter options that people might install. Currently we use WebdriverIO.Config
for that and allow services and reporters to extend service types so users only need to install the service or reporter and have type safe configurations. A way around this would be to have users define service like this:
import myService from 'wdio-my-service'
export const config = {
// ...
services: [myService({ ... })]
// ...
}
Currently users only need to do this:
export const config = {
// ...
services: ['my']
// ...
}
This has been historically been this way and something I am open to change since we migrated to TypeScript after we've defined these interfaces.
That said: if you know a way to allow us to easily extend the browser and element interface I am happy to explore ways to move to modules. Using namespaces has been challenging at times as you never know where the definitions come from.
Hi @christian-bromann @naruaway, thank you for your prompt responses!
Does this mean we should still be using WebdriverIO.Browser
? I tried both methods today, it still couldn't find Browser when it's WebdriverIO.Browser
, it has BrowserRunnerOptions
, Config
, Capabilities
, etc., but no Browser
.
On the other hand, import type { Browser } from "webdriverio";
works, which points to export type Browser<Mode extends 'sync' | 'async'> = Mode extends 'sync' ? BrowserSync : BrowserAsync;
.
This may have something to do with the version of webdriverio and its types we are using (webdriverio: 8.1.3, @wdio/types: 8.1.2), at this point importing Browser is not deprecated yet.
@xiaoyurenqa can you provide a minimal reproducible example where WebdriverIO.Browser
doesn't work for you? As long as you have webdriverio
installed as dependency it should have this registered to the namespace.
Hi @christian-bromann , I spun up a minimum TS project and tried it out, seems like WebdriverIO.Browser
is being detected without a problem, it might have something to do with how our project was set up that for some reason Browser
does not show up (but other types such as Config
does)...
I'll bring this to our team to see if they have any idea on why this happens. Thank you!
At first glance, I think the reason it doesn't work for us is because WebdriverIO
comes from @wdio/types/build
, whereas when it works, the WebdriverIO
comes from @wdio/globals
.
@xiaoyurenqa mhm 🤔 the WebdriverIO.Browser
and WebdriverIO.Element
types are defined as part of the webdriverio
NPM package. Is it possible that your project has custom types
defined in the tsconfig.json
?
Hi @christian-bromann , yes seems like we have to specify @wdio/globals in order for WebdriverIO.Browser
to work, thank you for your help!
We can probably close this issue for now.
Thanks for confirming!
Is your feature request related to a problem?
Mode: Standalone mode
We use webdriverio in its standalone mode, using TypeScript, and it seems like there is no way to declare the browser's type since it's not exposed. We found a workaround to get the type by importing browser from global, like this:
While this solution works, but it looks awkward and it is not able to automatically detect methods supported by the type (WebdriverIO.Browser).
Describe the solution you'd like.
It would be nice if webdriverio can expose the WebdriverIO.Browser type for import so that it can be properly declared in the project and can properly detect supported methods and properties when using webdriverio in standalone mode.
Describe alternatives you've considered.
Since the version we are using is 8.1.3, which is a bit behind, if there's already a solution to do this more properly, please let me know. I didn't find much discussions or docs out there for this issue.
Additional context
No response
Code of Conduct