 So, welcome everyone to the Selenium conference. We have two wonderful speakers, Srinivasan Shekhar and Shail Krishna with us. We're very glad to have you both here today. And let's, without any delay, jump into our session, build your own APM2 driver. Hey, thanks, Veena. Hello, everyone. Good morning, good evening. Different time zones. Thanks for joining our session today. And we're going to talk about how do you want to build your own APM driver. And along with APM driver, we're going to say APM2.0 with it. We are not going to touch base a lot into APM2.0 as a part of this session. We're going to probably talk at a very high level where are we with 2.0, and focus more on how you can build on drivers, which is some awesome stuff that APM2.0 has given us. Before we get in a quick intro about ourselves. Myself, Sai, and I work for ThoughtWorks as a lead consultant. And I'm quite passionate about open source. I do acquire a lot of open source contribution and an active contributor to APM, Selenium, Tyco, and also present in a lot of conferences as well. And yeah, that's me. Srinivasan Shekhar. Hi, everyone. Thank you for joining us. And I am Srinivasan Shekhar. And I'm also a lead consultant at ThoughtWorks. And I'm a contributor and maintainer for APM's Java Client. And contributor to various open source repositories, including Selenium, APM, WebDriverIU, Tyco, and a lot more. And I am speaker in various international conferences including Selenium Con, APM Con, Agile India, and a lot more. And these are my Twitter handles and GitHub handle. And today we are going to go through about what's the current state of APM, which is APM2.0. And what does drivers actually mean? And we are going to build one. We are going to do some live coding. Hopefully it goes, it comes up very well. And we are going to have a short Q&A at the end. But feel free to drop your questions in between if you have any. One of us will be able to pass in between and take it up and don't hesitate. Feel free to drop it. And we'll be able to pick it up as we speak. So APM has been there for quite some time. And it's more than six, seven years that we have a lot of dot versions on APM1.x. So it has gone through a lot of evolution. And each and every dot release has introduced new features, bug fixes. It has seen so many versions of platforms. I mean Android versions and iOS versions with a lot of new different features coming in and going out. So with APM and it's going to be the end of APM1.x very soon. And it's deprecated already. And we are in APM2 beta for more than a year. And it's going to be the way forward for everyone of us. And we are in a full swing in terms of updating our documentation. And it might soon hit the market with the stable release in a month or so. And the special about APM2.0 is the plugins that gets introduced in APM2.0's architecture. Plugins are nothing but a small piece of code that could help you to introduce in APM umbrella without touching anything of the code module. All right. And with respect to drivers, I'm sure with APM1.x, if you install APM server, it does install a bunch of drivers for you folks, right? Even our application under test that we wanted to write a test for probably on iOS, but it might also install several other drivers which we might not use. So this kind of a pain point for quite a lot of people. So we understood that and with APM2.x, it's going to be you install what you want. Let's say if I wanted to automate an iOS app, so you could only install iOS driver, which is the XC UI driver and ignore all the other drivers because you're not going to use it as of now, right? So you could you install what you want. So the drivers are decoupled from the server. So it's a new general decoupled the driver architecture that we moved into with also a support for plugins so that you could introduce your own piece of code along with APM commands to override it or to introduce a new command. In the APM2.x, so given that we have so many drivers we have already, is it possible for us to build a new driver in APM2.x world and how easy or how complex it is? Definitely it's pretty easy to build a driver with 2.x compared to 1. And there are just few steps that we need to follow to actually build the driver for us. How is it different from APM1.x? Because we have seen drivers hitting the market from community on APM1.x as well, right? So what's special about 2.0? See, definitely we could build drivers even in APM1.x. So we have seen quite a few drivers coming up that way, right? We have seen Flutter driver, which is maintained by the community. We have seen UI Engine driver to automate UI Engine TV apps and stuff, right? But with 1.0, you had to make some changes to the core module and one should also understand internals of APM as well. And there has to always be a connect between the maintenance of the drivers and the core APM team. So you see, these are the things that 1.0 had. But with 2.0, the kind of drivers that you could build, it's completely decoupled. So you own the driver. So you sort of decide how you want to build your driver and how you want to initialize your driver. So those are the capabilities that APM 2.0 brings in to build custom drivers for us. You don't have to rely or make any changes into the existing core modules of APM 2.0. But rather you build your driver and you sort of register that with a current APM server. And APM server can understand that, you know what, hey, there's a driver that I've got initialized and probably any commands flowing into me should get to this driver. It's that easy. That's great to hear. Let's build one. Yeah, definitely. Before we jump into build one, like I said, there are very few steps that we need to look through. The three steps that anyone should follow when they want to build any drivers is the interface implementation, W3C command mapping, and basically you build your driver. When we say it's an interface implementation, what that means to us. See, APM driver is just a bit of code that inherits from some other code within its core APM model. That's it. And now inheriting from the base driver actually gives us a lot. Because the base driver is essentially an encapsulation of all the web drive protocol commands for us. And so what that means is, so all the driver needs to do is something useful for them to implement. See, we just said that there's a Flutter driver or probably a UI engine driver. So or even let's take our UI automated to the driver, like a lot of drivers you spoke in a previous slide. So these drivers, they should actually know the responsibilities. And that's what this W3C command mapping polls. The driver authors, they should know the internals of the platform that they're trying to automate. Let's say that you want to automate a Raspberry Pi. So first of all, even before you automate a Raspberry Pi, you really need to know what you want to automate there. And you need to know if I have to automate what are the commands that I need? Like how do I interact with Raspberry Pi? How do I make the connection? So those are the some of the basic things a driver author should know of how the internals are working. And all that they have to do is once they know that they'll have to map all these required commands to the W3C protocol as simple as that. Because you see over here, the core thing is about mapping them registering to the server. And once you map it, what is that mapping going to do? That's the important key that the driver should actually know as authors. And the third part is definitely you build a driver and you simply register it to the Appian's to core. And it's that simple, Srinu. Wow, that's nice. Maybe we should try to build one. Sure, let's do that. Cool, I have some bad email template probably. You can take us forward with that. I see Srinu is actually build a simple template, a Node module, a Node.js project. Why Node.js? Simple answer to that. Appian server is a Node.js and your plugins and drivers should be in Node.js. It's as simple as that. And that's the reason you have to build your drivers in Node.js. Okay. And we'll go step by step. There are like, like I said, there are three steps, right? So let's look into those three steps and what is the prerequisites as well? So when you build a bare minimal driver, the first thing when you do an NPM minute, right? It gives you a basic empty Node package. So go into your package.js and the first thing you need to do is inside your dependencies, you add your dependency called your base driver, right? What Srinu is highlighting. So that's a dependency that you need to add. That's the first thing that you have to do. The second thing is what you need to do is forget about the other dependencies for now. Basically, we'll come to that. The second thing that you need to look at it over here is in line number 47. You need to create an Appium object over there, which is basically got certain attributes in it. It's got a driver name, automation name, certain platform names and main class. Okay. So what are these, right? A driver name itself, it's pretty self-explanatory. It's going to say that, hey, what is the driver name that you want to call, right? A meaningful name that you want to give to your driver. And why do you need a driver name is because you have to tell Appium, right? Hey, this is my driver that I've installed. And this is the driver that you need to activate, right? And that's the reason why we actually need to give the driver name. An automation name, right? Like any other drivers that you have today, like your UI automated to or ExpressO or XEY. If you have built some basic scripts in Appium, you would know that automation name is mandatory. You need to tell whether it's an XEY or a UI automated to because the internals of Appium says that based on this automation name, it's going to load certain required node modules for us. Okay. We'll keep it at that level at this point of time. And when it's platform names, right? You simply tell that, hey, this driver can only support an Android or the driver can only support Android and iOS or probably can only support a Raspberry Pi, right? Something like that. So you need to tell which platform your driver actually supports. Okay. And then you have a main class. It's nothing but, you know, like any other programming, you want to create a class and you want to name it and that's going to be a main entry point for this driver. So you're going to give a main class name. Right now over here, we have simply named it as Appium template driver. It could be anything that makes sense to build your own driver. Okay. So the main class should have a name and you have to tell, you know, Appium, the node which we're talking about to say, hey, this is a main class and you need to load everything there. That's the entry point for us. Okay. And now where does this main class reside, right? So you see this line number five, which is getting highlighted again. It's dot slash driver slash driver.js, right? So you create a class. You create a file called driver.js, create a class called Appium template driver, whatever you have created down there as a main class name, you simply create that. So can you open the driver.js? So we have created some basic things keeping our time in mind and we didn't want to go everything ground up. So you see this, right? So you have an Appium template driver as your main class name and you see over there, the class name should exactly match. Okay. So they both need to be same. They can't be different. Please keep this in mind. They have to be same. Okay. That's the main class that we're talking over here. Okay. And I also see as a part of the main class, right? It extends a base driver. So if you go back to the previous slide, you remember, I was talking about the first step is about interface implementation. So basically this is where this is a base driver, which is basically an encapsulation of all our W3, all of the driver protocol commands. Okay. And there are certain things as base driver also exposes for us for basically it helps us for certain things in our building of the driver. Okay. And Srinni, I also see in the constructor in line number tell, you have something called as this dot desired cap constraints. What's that Srinni? Why is that needed there? So each and every driver are activated by base driver behind the scenes through an automation name. Let's say we have two different automation back ends for Android, a UA automated to one Espresso for Espresso driver. So base driver text reads these capabilities and these capabilities is mandatory for any driver. So we have defined that constraint here that automation name, which is has to be present and it is of type string. So we just need to define it here, but the validations will be taken care by the base driver itself. Okay. And so this can also be any, any capabilities that the driver would need Srinni. Yeah, definitely. For example, let's say if we wanted to add browser name here, we could definitely add browser name and specify whether it is mandatory or it's of type string and yep. So let's say browser is also mandatory. So you could add it as true and it's of type string, then you can say that. So we basically define the constraints here or the driver. Cool. Can this capability be anything, right? See, I know this automation name and browser name. They are like something which is very common even in our Appium code, right? So can this capability be anything? Can I name it like, you know, template driver weight? Can I also name it something like that? Yeah, definitely you could introduce your constraints. Cool. So, so that means with this, the base driver also is doing all this kind of validation and as a driver author, we don't have to take care of any of these validations, right? Yes, exactly. Sounds good. That's, that's exciting. That's really cool. And I also see Srinni in line 21 and 27, right? You have created two functions which says a create session and delete session, right? I mean, of course, the function, the method name is pretty self-explanatory. We know it's creating a session and deleting a session, right? I mean, why have you explicitly mentioned it as create sessions Srinni? Why can't I just name it creating a session? Or why can't I name it create under session, right? Or why can't delete be a deleting session? Is this, is this some side of, you know, pattern that we have to follow? Why have you specifically mentioned it as create and delete session? So as we extend base driver, base driver holds all the routes that Appian supports and the commands which Appian supports or gets called inside it as well. So let's quickly see what kind of, I mean, what kind of commands that we have. Let's say I am inside Appian's base driver module. So we see there is, I mean, we see there is a route.js here and which also talks about different, I mean, all the set of W3C commands that Appian supports. So it has the kind of registry for what kind of API calls that it makes internally. And it depends on the driver, whether the driver, for example, Android driver might support X set of commands and iOS driver might support Y set of commands, but you will find all these commands out here in the route.js. Even if you see here for creating a session, it says what kind of API that gets exposed and what kind of command that it gets called internally and whether the arguments for those are optional or those are required. All of those are defined here. And we just read, I mean, we just have to say the same command name when we were implementing it in the driver. For example, we are implementing it in our template driver. So I use the same name as what we saw here for create session and same for delete session as well. You might find with the delete command here under the hood. Yeah, you go here. So we have the session ID. It takes a session ID and the command for it is delete session. So that's the reason why we specify it at the same name as in with route.js commands. Sounds good. So which means from any client now, let's take any client, right? It could be Java client or WebDriver.io or any client we have in Selenium. Whenever an object gets created, like, let's say an Android driver or iOS driver, right? When any such objects get created and when this driver is registered, so you're saying that it would get into line 21, right? So this this create session would typically get called, right? Yes. And if I have to implement all the W3C WebDriver protocols for my driver, all that I need to do is I need to go to route.js and see what are all the commands that APM has got. And I need to map that with the protocol with W3C specs, right? Exactly. Sounds good. Sounds good. Cool. Okay. That's pretty easy. I see that we could the way we could map in and build this drivers, right? So what is that we're going to build today? So I remember going through some of the pain points in past for an enterprise client where I had to download Chrome driver very often and it has to go through a lot of tickets and then behind the proxy test to go through some kind of screening from the security team and it has to be placed on a separate path as well. And all of these takes time and before we get there probably we hit another release of Chrome. So since Chrome DevTools protocol is gaining a lot of traction quite recently and it doesn't need Chrome driver. It talks through WebDriver. I mean it does talk through WebSocket communication instead of WebDriver. I mean instead of Chrome driver. So given that we are getting a lot of traction around that and there are tools, amazing tools built on top of it. Like for example we have Puppetter, we have Playwright. We also have our own Tyco built with in ThoughtWorks and open source, right? So why don't we build one called Appium CDP driver? So I want to mute. So you're saying that we could build this driver where this driver is going to interact with your browsers on your Android devices? Like any Chromium based devices, any Chromium based browsers, right? It could be a Samsung Internet browser or a Chrome browser or a Brave browser. Any of those which is based on Chromium rights, really? Exactly. Sounds exciting. So how do we do that, right? So can you tell us like how are you going to connect? How are you going to make this connection between the server and your code, right? So how is that we going to do? So we need to make a port forwarding first so that we can establish remote connection. So I have my handle device, Android device and which is connected or displayed here through Wiser. So we have a Chrome browser and I mean, Chromium based browsers in my deck, I mean in my mobile. So we need to have some kind of a remote connectivity. So probably let's establish that connection first. We could see that I have a device here that's connected and probably let's do a port forwarding first. So I did kind of a port forwarder just to make sure we have a remote connection. And each of these tabs that I have opened, I think I have opened some 48 tabs or so since it's my personal device. So each of these tab exposes WebSocket Debugger URL. Probably we can use the Debugger URL which is opened remotely. We can hook into that Debugger URL and give the Debugger URL to one of the CDP implemented tool sets. Let's say probably for now we can pick Tyco because we have been contributing to Tyco a lot. So you are one of the co-contributors. So we know the internals of it quite well. So we can pick that and we can give this Debugger URL to Tyco so that the interaction happens via remote and under the hood it Tyco takes care of it. Cool, cool. So I have a question here. So you're going to talk about, you actually basically port forward it and you're going to talk about, you're going to take the WebSocket URL and stuff, right? So how are you going to fix this WebSocket URL scene? Exactly. So I did launch my browser. It does us some number of tabs already open. Let's see if we are able to get it. Since I have port forwarded to nine to four one, we can hit this URL called JSON list and see it does features. It does features some amount of WebSocket URLs here. So you're basically in this WebSocket URL to connect to the specific browser so that you could run your Chrome DevTool protocol commands, right? That's what you mean to say here. That's pretty cool. And this is what I was actually mentioning in the previous, right? In the steps where you have this WCPC mapping, the driver authors should actually know the internals of the platform that they're trying to automate. And this very clearly shows that Shrini right now knows the internals of his platform that he's trying to automate because he knows that the browser, you know, how do you port forward so that you can open a connection? And along with that, he knows that if you get to the JSON list, it would get a WebSocket URL and through the WebSocket URL, we can like make a connection to the browser and send any commands into this, right? And this is where... Now, all that we need to do Shrini is because you know the internals of what you want to do. So we're going to basically map whatever you're trying, whatever you did manually into our WebDriver protocols, right? Exactly. Sounds good. So we can do all of these things. Like for example, I have opened a tab and I also have done port forwarding and also I have hit the URL and fetch the WebSocket URL so that I can give it to Tyco's to open a browser, right? So I can do all of these things, what I have done manually inside Chrome sessions or create sessions so that we were able to do everything programmatically. So Tyco takes care of all of these things. And for port forwarding, we used the ADB command. Probably we can use one of the APM-ADB node modules so that it takes care of port forwarding as well. Sure. Maybe you can help me take me through the stuff. Yeah, sure. So I see the first thing that you did was you basically ran a port forward, right? So to do a port forward, you basically need to get a connection set up with ADB. So it's basically a thing, but an ADB starts over, right? So get ADB. So yeah, I see you already have this get ADB, right? So which means you already prepped for these commands, right? For us? Yes. So whatever I have done manually, I have it in ADB.js. So get ADB takes care of creating an instance and then some other commands. Also, it does ADB.js also have a command for port forwarding. So whatever I have done manually, it's already been added here programmatically. And I have launched the browser manually, right? I have activated the browser tabs manually when I am trying to load the Chrome tabs, right? So that's what start application does. So we have this scripted already. Sounds good. So the first thing I see that you open this and you also did a port forward next. Yeah. And the next thing that you did after a port forward was you actually opened your browser in your phone. Yep. I have a startup position which internally activates the tab, the activity. Okay. Okay. And again, you have used a simple ADB start activity, right? Which is coming from Appium for us to start the application. Sounds fair. And once you started the application, you basically went into your browser. You like sort of poked your, you know, yeah, the list, right? Wherever your browser is running with all the protocols. So you basically have to fetch one of the WebSocket debug URLs, right, for us? Yes. So it's kind of a target for me. So I need to get at least one WebSocket debug URL so that I could establish socket connection. So I have a sample. I have a subcode which is already written which could help me to get the target. So what does it do internally, right? So if you go inside, it just simply makes an API call to JSON list to the port number that gets created. And it gives me the JSON response and it kind of keeps on redrawing. And we are getting the target for Appium.io. As we see, there are 48 tabs that I have opened. The title could be different for different and URL could be different for different, right? So I am trying to fetch the target for Appium.io and the Appium.io is getting launched by default by FPMADB. So that's what I do here. I can't get target. Target kind of gives me the node. So from target, I can able to get the WebSocket debug URL. So now that I have all the pre-setup, probably we can hand over all these things to, I mean, we can hand over the WebSocket URL to Tycho. You know the hand that I could use. Yeah, it's an open browser. So we should typically try to open the browser now. And to the open browser command, you basically give the port, the target and the host. Okay, port number. Where do we get the port, Stini? You never spoke anything about the port. So when you're doing the port. And what port is that? So I get the forwarding, right? It does give me a port number where the forwarding has happened. So here in our case, we have forwarded it to nine to four one. And we use the same nine to four one to fetch the list. Right. So in case of programmatically, we are trying to get a free port in my Mac machine. And it does returns that free port once we have initialized. I mean, once you have done the port forwarding. So we are going to use the same port here. So that Tycho can talk to the port. And then you give the post. Post. Post is basically a local post. I mean, we can give 127.0.0.1. And we also have to give target. It's target. It's target. We also have to supply the target to. So target kind of gives me the complete object. But what we exactly need is web circuit debugging URL. So I will take this web circuit debugging URL and supply this to Tycho. Open browser is something that comes from Tycho. We have it imported from Tycho here. If you see here. Yeah. And you see over here, right, as a part of create session, the responsibility of the driver over here. So responsibility of streaming was over here to tell that inside a create session. What is that you really want to do in your driver. So it's very important. The authors of the drivers should know what is that they need to do inside each of these W3C mapping. So create session is definitely something that is a private protocol. Right. And inside that it's the driver's responsibility to do whatever they need to do. And that's exactly what we have done over here as well. Yes. Yeah. So now with we have actually opened a browser. Right. We have created that sort of a connection alongside. And it also shows us another implementation from a web driver protocol. Like probably maybe the first thing generally, which we tend to do is you actually set a URL. Right. So what is that, what is that command that you want to do to setting a URL over here? Maybe I, I think we can go back to router.js and see what's the exact command to, to be implemented to launch a new URL. That's for it. Okay. I see there are two commands. One is set URL and another one is set URL. Set URL also takes a payload param, which is required as mentioned in the router.js, which is taking a string called URL. So probably let's implement set URL. And it's a param called URL. Okay. And just copy set URL. And I go back and implement a sync set URL. So since set URL is something, I mean, launching the URL in a browser is something that's been already done by Tyco using a command called go to. So we could, instead of reinventing the veil, we could assign directly. I mean, we could call the Tyco method directly and Tyco take care of heavy lifting for us rather than be doing it. So I will just say await, get URL, go to URL. And I will also return it. And this go to is something coming from Tyco again. So you could see here go to is coming from Tyco again. And instead of us waiting for navigation to complete, I will also say wait for navigation. And I will disable that for now. So these are all options that takes care. I mean, that can be given to Tyco's go to. So wait for navigation is disabled now so that it comes out immediately rather than waiting for the URL to become completely launched and everything goes idle and then coming out. So, so the set URL is a command that gets called when let's say driver dot URL in WebDriver.io is getting called in a client. It internally makes a call to this API called the slash URL, which will get called, which will internally call the set URL method, which is the implementation that we are doing in our template driver to be honest. Yeah. And we have three commands implemented. One is create session and for delete session, we are just giving the responsibilities back to driver, base driver itself. So base driver can take care of cleaning that session. And we also have a set URL which will take care of launching the browser, I mean, launching the URL and the browser that it has opened. Sounds good. So, so do you have a, do you have a sample test first to run and show Sunee how this could work? So I have a simple test here wherein if you go inside, it's a WebDriver.io test again. I have picked up WebDriver.io client. WebDriver.io internally takes care of driver initialization, not like Java client where you have to give new Android driver, new iOS driver where it takes care of initializing. So WebDriver.io takes care of it pretty smooth internally. So you don't have to do all of those heavy lifting in terms of capabilities as we have said before. So it needs this capability exactly. And here I also specified CDP probably I think we have to go back to a package that is an update our name of the driver which you have informed us or updated us in the beginning. Probably let's make it a CDP driver and automation name as CDP. So we could use this automation name inside our test spec and write capabilities. The mandatory capability here is a CDP, I mean, which is the automation name and and remaining ones are all usuals. And in terms of test, I have a simple test which will launch the URL, which is driver.url of Google.com. And also it deletes the session once everything is complete. It just winds up deleting the session and comes out of it. So maybe we could try running this. Yeah. Okay. Let me quickly start our Appian server. So I'm initializing the Appian server to use only the CDP driver. And just to call out, this driver is already being installed because installing a driver takes a little bit of time just to save some time we have already installed it in our machines before this. And that's why she need directly start up the Appian server using the driver. So I have started the Appian server now and you could see that it is using the CDP driver that we have implemented and I have a couple of other drivers too. It looks like I have a UI automated to driver, but for this session it's going to use CDP driver. Probably let's run the test with CDP driver and see if everything goes smooth. I have my real device and again the 48 apps are already open. Probably let's quickly run this test and see if everything goes smooth. So right now then all the calls would typically come to the driver which we just built, right? Yes. Okay. And how do we know whether it's coming to our drivers? Looking at the Appian logs, do we know is there a way for us that it could typically come in? Yes, we can see here it's creating session with W3C capabilities and these are the capabilities that we have specified and also you could see that Appian template driver is the driver that we have built and this is the driver that we have built ourselves. So Appian driver kind of gives the responsibility to Appian template driver as the session got created and you could see the session ID and it's also getting the WebSocket URL, it's able to get the WebSocket URL as well here and it's waiting for launching the URL, I mean set URL basically. Yeah. And Sunee, what is that in the logs, right? We're talking about creating a session over there. So it says Appian template driver. So where is that coming from actually? Yeah, we can go back to our code. We also have a logger. Probably we could see logger.js and here's the name that we have specified as Appian, I mean just template driver and Appian, it's kind of prefixing it with Appian template driver. Okay. And so my question was other way around Sunee. So my question was around, one is the logger. I mean that is something where you typically say that any information can be logged to the driver, right? So is this the Appian template driver what you have over there, right? Next to creating a session. Is that the same name what you have given in main class or is this the different name? This kind of the same name that we have given it. Okay. And that way we know that these logs are coming from the driver which we built just now and not from the default core modules of Appian, right? Exactly. And we also have some certain logs inside. For example, if you have seen, we also have some logs added here which says probably inside template driver create session might get logged here somewhere. Yeah. We see that there Sunee, you have used it for the URL, right? So you see template driver URL is WebSocket. Yeah. Just before shutting down, right? Yeah. That's the template driver. So that's the logger, right? Which we register. You're right. Try to initialize the driver and do another run. Okay. I have my spec here. And the server is up and running. So it's kind of creating the session. It is launching the default Appian that I was well. And you could see that it is launching Google.com because in test we were asking it to launch Google.com and quickly going back to our Appian server logs. You could see template driver URL is this WebSocket debugger URL. And you could see new Appian template driver session getting created successfully. And once create session command is done, let's say, once create session command is done, you could see that the session gives me 200. We also see it gets, it calls set URL with Google.com. And the result is again 200. And once set URL is done, it makes a call to delete session. Sounds good. So that means it clearly maps everything into our driver, which we will write. And this way, anyone who wants to build their own custom drivers as authors, you have to know what you need to do. And you simply have to map all the WebDriver protocols the way we did for set URL. And you can actually get going. So we just took an example of set URL over here. So we have actually published the first beta of the CDP driver. It's there. And probably you can go ahead and install it. And we'll be in the hangout rooms after this so we can give you all the links and stuff like that. So you can also go ahead and try if you want to choose to automate your Android Chrome or many Chromium Brave browsers on your devices through Appium. You could give that a shot. Cool. So it can be like very quickly run through a recap of what we did for the last 20 minutes. We built a driver. There was a bunch of stuff. So let's do a very quick recap with steps. Step one, you have to have this dependency in your package.json. And inside that, you also have to call an Appium node, which is called the driver name, automation name, and platform. And step two is you have to create a main class. And the name has to be the same what you have given in your package.json inside the Appium object. And that needs to extend to your base driver because we didn't say that base drivers is encapsulating a lot of these WebDriver protocols. It's going to help us a lot there. And the step three for us is you'll have to simply map your W3C commands. So setURL was one. You set the URL and you write any logic over there to open the URL. And from the client side, we simply set a driver.getURL, which would typically call your driver. And your driver's responsibility is to handle the setURL. And your driver has to take that to, say, set a URL or openURL, whatever it needs to do over there. And the third is definitely is a build. So the third step is to build. So which means there are commands to build your driver. So you simply run certain Appium CLIs to build your driver there, which is driver.install. The source can be local. So during our active development, you can install, you have to keep installing it locally before even you publish it to the NPM registry. So you could use source as local or once you've published it, like I said, we have published the CDP driver already. So you could say the source is NPM and the driver package name can be CDP-driver. And once you do that, when you start your Appium server on 2.0, you have to say hyphen hyphen, use drivers, and you give it a driver name. Maybe you want to bump in two, three drivers, you could give it a comma-separated. Or if it's one driver, give it only one driver name, which is the CDP driver for us in our case. With that, there are also a lot of drivers where the community is already built like a Unity driver. Unity drivers, if you see Unity games, so if you want to automate your Unity games, check out for Unity driver. So the slides that got links will upload the slides in Confingent, not to worry. So the Chrome DevTool protocol is exactly what we did right now. So we have some betas published. So you can give a try Roku drivers to automate Roku TVs. And UI Engine, so that's another driver. So there could be a lot of drivers, but we just found few, whatever we have seen and we have heard in the community and we just added that over here. If you know that you are building some more drivers, please reach to us. We'll be happy to take a look at it and maybe we can familiarize with the community as well. And with the drivers, we also have plugins because Srini said that mentioned that in the state of Appium, 2.0 brings drivers and plugins in isolation, right? So similar way, there are a lot of plugins. There are certain plugins which is maintained by the Appium Devs. There are certain plugins which is a community built like Appium Wait is a community built plugin, Device Farm, Gestures and all the last four are purely community built. These have links, go check this out when you're trying with Appium 2.0, hands on. Yeah, that's about the plugins and the drivers which is available to the community. Like I said, we know some, so we have done that bits. Cool. We have a workshop day after tomorrow. If you want to know more, hear more about Appium 2.0 and the advanced stuffs related to Appium 2.0, feel free to join us. And that's us. Thank you. Thanks everyone. Thanks for holding on and being patient and listening to us. And we are open for questions. Thank you so much for this very insightful session. Srinivasan Shekhar and Shahi Krishna. There is another question, Sai. Where can we find this sample report to build drivers? So, want to take that up? Yeah, we have a template created what we just did. So I'm going to quickly post that in the chat as well over here. And also we'll add that as a part of the slides. So when you go to Confingen, you can also find the template driver link over there.