 Good morning, everyone. Welcome to this session with Sai and Shrini. They are original contributors pretty much to the Appium project. They've been with it for a long time. They were just telling me they've been contributing for seven years now. So they've been around a while and they know a few tricks and they're enjoying playing with Appium 2 and some of the things they can do with that. So today they're going to be discussing building your own Appium plugin, which is one of the new things I believe you can do with Appium 2. So over to you guys. It's all up to you. If you want to have just before that, if people have questions, please put them in the Q&A and keep the chat for other things. It's just easy to find them. Sai and Shrini are going to answer questions as they go. So we'll pick things up there. But yeah, if you can drop your questions in there, that would be great. And this time it really is over to you guys. Thank you. Let's get started. I see people coming in. That's cool. And I would just want to start off with thanking people joining this session. And as part of this Appium conf, you know, we have a lot of talks around Appium 2 plugins, drivers, right ways to build stuff. So our talk is about how do you want to build a plugin? So let's get started. Let me start introducing myself. I'm Sai Krishna and I work as a lead consultant at the Works. And I've been contributing to Appium project for roughly about seven, eight years now. Including Shrini. So we both were pairing together for a very long time on the project very early days. I also presented multiple international conferences, an active contributor to Appium, Java Client, Selenium, Drive.io, a lot of other open source libraries. So my passion is to contribute to open source. So you learn and give it back to the community is what I believe. And you can reach me on Twitter and that's my Twitter handle and my GitHub ID as well. So we have some cool, interesting projects as well. If you jump into one of our GitHub's you would find out. And over to you, Shrini. Hi everyone. I hope you are all safe and sound back home. Myself, Shrini Vasan Shekhar. I work as a lead consultant at ThoughtWorks and a contributor and maintainer of Appium's Java Client and contributor to various other open source repositories including Selenium, Drive.io, Drive.io and that's me. Today we are going to talk about why Appium products zero and what is Appium plugin and when do we build Appium plugins and we are going to build one now. And we are going to have a live coding session and a short demo on couple of plugins that me and Saiko have heard. Cool. And Appium is a text architecture. As you know, Appium is a client server architecture. You write your test code on any of the client libraries which Appium supports and which internally talks to Appium server in a W3C web driver standard which internally talks to one of the driver that you wanted to talk to, which could be Espresso driver or UI automated driver which internally talks to the server running which is Espresso server running on device which talks to Appium, I mean application under test. That was Appium 1.x. From Appium 2.x, we are going to have another one called Appium plugins. So the client libraries will talk to Appium server and Appium server will take a decision, depends on what kind of commands that you are going to execute. It depends, I mean it takes a decision in terms of sending direct request to Espresso driver or XU driver or UI automated driver or the plugin that we have built and the plugin can talk back to Appium driver. It can talk to Espresso server running inside your test and which internally talks to which internally talks to the application under test. So we have this plugin that can be plugged into the existing, I mean the upcoming Appium 2.0 decoupled driver plugin architecture that anyone can build a plugin and plug into the existing ecosystem and make sure it works smoothly without modifying the code base of Appium Excel. So that's where the role of plugin plays a vital stuff in Appium 2.0 architecture. So we are going to talk about what is Appium plugin and when do you want to build an Appium plugin. So there are three situations that you can build an Appium plugin. One, let's say you wanted to add a new functionality altogether into the existing set of Appium commands. So let's say, I mean some of the Appium commands that have been widely supported in multiple platforms that we run are find element creating a session, fitting the session right. If you want to add more logs, let's say if you want to add more logs to the existing commands, you could do that. You just need to modify the existing Appium command by adding an arbitrary functionality which could execute before finding an element, just an add a log that I'm finding an element. After finding an element you can add a log saying I found an element or I don't found an element. So likewise you could add or modify the existing commands. Let's say you wanted to introduce a new command on top of the commands that Appium supports you could do that. And if you want to, let's say you wanted to come up with a beautiful reporting wherein in a real world says you have a report portal. Let's assume you have a report portal, which needs to start in its own service. I mean it needs an express server and it needs to start in its own service which might be running in its own port number and so on. So if you want to bring in those kind of services, you don't have to create another express server. Appium now exposes that server object itself wherein you can hook into the Appium server and create your own endpoints which could thus probably reporting for example. So these are the three situations where one can build Appium plugin. One is adding a new function. Next is modifying the new function or overriding a function or probably exposing the Appium server object itself which listens for certain kinds of requests. These are the three situations where you could build an Appium plugin and let's go ahead and see a live coding session on how you could create your own plugin. So Srini said about live coding. So this morning when me and Srini were having a chat and Srini wanted to do a live coding and I said probably it's quite dangerous to do live coding in live conferences but Srini was still sticking to live coding and I was not doing it for it. So even now I didn't say we're going to do live coding. I put the agent as demo Srini says live coding but I also want to hear from people in this room. You know, can you simply put out in the chat saying whether you guys want to see live coding or simply record. We have a video as well recorded. So probably some slides, talk through and stuff like that. I'm leaving it to you guys now to see whether you vote for Srini or to me and I'm just going to give like few minutes. And I see people keying in live coding first and then we see the recordings. Okay, live coding, live coding. Okay, so a bunch of, bunch of folks. Oh yeah, it's flowing in. Everyone says live coding right Srini. So you win this voting. Okay. But before I start, before we start right with live coding, I want to call this out disclaimer because you guys shows live coding and the recording and I was opting for recording and I'm going to live coding and Srini is going to play with me. So everyone here keeps saying that live coding, no issues if any problem comes up and all those beds. Okay, we'll have coding but starting the disclaimer live coding dangerous. And now I have a lot of people to blame if something goes wrong because you guys ask for the live coding. Right. So let's get something to see what we can do and how we can build a plugin. Okay. And Srini, you're going to help me with this because you're the one who we're very sticking to it. Say you want to do live coding and people in this room also want to do live coding. So let's see how this goes. Okay. Sweet. So we have built an empty project, which is a Node.js project. Why Node.js? Simple. Appium server is a Node.js. So which means your plugins should also be in Node.js as simple as that. Okay. So we built a simple, empty project that says Appium.conflugging. It's got a test folder. We'll come to that. No worries. We have a SRC and we have a package.json. So what is this package.json got to do here? Okay. So we have certain callouts to be. Forget what's under scripts. Basically, those are something which can help us run tests and bits like that. Step number one, to build a plugin. You will have a package.json as a part of your Node project. So first thing you need to come in over here is and look for these dependencies. You need to add Appium-based plugin and support as a part of your dependencies. Okay. Step number one, keep in mind, you need to have this dependency called Appium-based plugin and an Appium support. So that's like step number one, which is mandatory. Dev dependencies, you know that it's basically helping us to do some sort of linting, writing our tests, some dependencies which is required. We really don't have to talk about all of this over here. The next part is this, the Appium object. So you need to have an object in your package.json, which says Appium and it's going to have two attributes, which says plugin name and main class. And plugin name, it could be any name, right? In our case, we want to name it con-fifendemo. Maybe in your case, you might want to name your plugin something meaningful of what your plugin is doing. In the previous plugins with me and Stine built, we named a device farm and we named gestures, we named element weights. So they mean something out of it, right? And so plugin name, if you give it a name, and a main class. And a main class could be any class name, right? And the attribute itself clearly says, hey, it's a main class. So which means con plugin is going to be my main class name. It's basically a name. That's it. Okay. So these two things are quite important. Step number one, I'm calling it all again. Appium-based plugin should be in your dependencies. And Appium, an object called Appium, which will have two attributes, plugin name and main class. So that's your step number two. So step number one, step number two is done. So let's see what is step number three. So you get into, so we've created a file called plugin.js. And this is step number three. Okay. So you come to this plugin.js. I mean, you can name anything. Okay. We have just named it meaningful, saying plugin.js. It can be a.js, b.js, et cetera, et cetera. Because we have an index.js here and we're just simply exporting it out. Okay. Nothing fancy. So here comes our step number three, which is you need to create a class and the class should exactly be the same class name as we have called it out in the main class. Okay. So we got to say export default class. That's my main class, which extends our base plugin. Okay. So you need to extend the base plugin. Okay. So we extended the base plugin. And now we need to import the base plugin, right? Like any other project. You need something. You import it. So I say a base plugin from, and that's going to be from the Appium's base plugin. Being all simple. This is your step number three. Step number one in your package.js on, you add your dependencies as Appium support, Appium base driver, a base plugin, and you have an Appium node. And this is your step number three, which is you got to create a class, which is exactly the same over here, which matches to this guy. And then you say extends base button. That's your step number three. Okay. So now we have built, we have created the skeleton. Okay. So we have created a skeleton out there. So let's try filling in certain bits into this now. Okay. And so Stinead, you did mention that there are three things that the plugin can do, right? So one, updating the server object. Second is you can modify a given existing function. And third is we can write our own functions, which means you can write our own end points and implement our own plugins, right? Cool. So where do you want to start now? Do you want to start with modifying something or do you want to start with writing something new? Yeah. Let's start with modifying find elements. You want to modify find elements. Okay. So async find elements, I'm going to modify this find element method. Okay. How do you know that? It's called find element. Why not it is find apium element internally? How do you know that? That's a pretty good question. So let's go to read me. I've just kept that link out. Probably I already have it here. Okay. So if you go to your route, right? If you go to your apium base driver and you look for route.js. So that's where you have all your routes, what currently apium is holding. Okay. So now Stinead said that he wants to modify find element, right? So let's see if we have something called find element. Yeah, we do have. We have something called as find element. That's an endpoint. And then we have a command called find element which takes certain parameters. So let's not worry about what the payload is, but we are more focused on that specific command, right? So we got to exactly write the function name, what you see over here as a command. Okay. So Stinead answers your question, right? So we copy this find element and that's exactly going to be my find element over here. Okay. Bingo. So we have done that. Let's add some logs before executing or before finding an element. Sure. So we got to add some logs. It's a different way to add a log. So you could also use console log, which is default from node. But I want to get these logs into my apium server as well, right? Why do you need to see the logs from your plugin into the apium server? Of course, because you are building the plugin. And if something goes wrong, you want to basically log, right? So you want to say that, hey, I'm trying to perform an ad. I have performed the ad. My ad was successful. So you basically want to tell the user saying that what sort of actions have gone and prove it more information so that something fails. People can give you the logs, right? So I don't want to use console logs because apium does expose something called as logger. So let's go import that, Sunee. I hope that's fine with you. Or do you want to still stick to console logs? Makes sense. Makes sense, right? So, okay. So he agrees with me. Okay. That goes good. And so we did this. So let's just simply console log equals to logger.getLogger. So that's how you actually create an instance of the logger. The logger needs a name. So can we say this logger has console plugin because we are trying to build that plugin, right? Okay, cool. So in this case now, Sunee, we say info.log.info. And then we say we are at apium.conf 2021. I want to put a smiley. Let's all be happy. I want to put a smiling face with open mouth. Okay, cool. So we did this. Now, do you still, do you just want to find the elements, Sunee? Or you want to like, you said you want to modify it, right? So which means do you want to do something? Okay, cool. So in such a case. Okay, so you said you want to give the control back to apium, which means the find element has been modified, right? Where we modified that by adding a simple logger here. And then you're giving the control back to apium. Sounds fair. So here, this find element exposes certain attributes to us. One is next. We'll talk what is next. And driver and hyphen hyphen args. Okay. So what driver means is basically it's nothing but your simple driver, which is going to give you the entire information about your driver. And the next is nothing but what we have to call now. So we simply say return the next. So what this next means is, so the plugin is actually indicating the server saying that, hey, my job is done here. I want you to do the next part of it. So that's what next means over here. So we're giving the control back to apium server saying go ahead and now you continue to do what you are supposed to do. As a part of the, you know, fine, fine elements. Okay. So I'm not going to print out to see what driver and args have got, but do you still want to do that? Do you want to see what driver and args have got? So basically drivers got simply the driver information, like session ID, maybe a port where your server is running and a lot of bunch of information. Okay. And args are nothing but whatever arguments is sent to the find elements, like your, like accessibility ID, you know, fine, a strategy is access ready. And value could be login, blah, blah, blah, right? So that's what is going to send that. Okay. So we have done this, right? So are we good with this? So we did a find element. We have overridden find element in line number nine. So we have modified it saying I want to see these logs. And then we said, give it back to find, you know, give it back to the driver. Sounds good. I think this is a good start for us. So what, how do we test this, right? So we definitely need a test to be there. So what we have done is we've already created a simple, you know, web driver test. Nothing fancy, pretty straightforward. We have a simple web driver IO test, which has got some default capabilities with an app over here and some web driver IO arguments like a port number where your Selenium, where Appium is running. And we're creating this session and we're trying to click on a log, click on a login and we're trying to delete a session. Okay. So just to call out over here, we are not trying to get the test passed. That's why we don't have any assertions and stuff. All that we want to see is how our plugin is, you know, getting merged into Appium server and how it is responding to it. So you see this, right? It's a driver dot dollar. So that's running my driver dot find element for us. So when this command is executed from the client, we are expecting it to come here and it should print this out to us. Okay. So that proves that the find element is coming to our plugin and then it is going back to Appium server. Okay. So let's do that. So let's add a wait statement there. Oh, where do you want to write an await statement? Line. Line. Bring it back to next. Oh, you do want to do it here? Plugging plugin.js. Wait, wait, wait, wait. Plugging.js. Okay. Yeah. What do you want to do here? Plugging.js. Line number 10. Let's wait for the finding element to happen. Await next. All right. That's a good catch. Yeah. Await next. Good. And Sini, why did you put an await? Cool. So we are, we also have to wait until the actual Appium driver to find that element, which is the UI automated tool server, which is going to find that and use as the response code. So we have to wait for it. Sounds fair. I mean, I agree to that point. Cool. So we, we built, we, we got all the, you know, building blocks. So we put the Legos together. So we have something to find element, right? How do we test this? So we have a test as well, but we know we should also install the plugin first, right? So how do we want to install the plugin? So before we install the plugin, I'm just going to first uninstall it just to make sure that I don't have the same plugin installed in my machine. So it says Appium plugin uninstalled conf demo. That's an interesting part, right? So what is this conf demo? So that's exactly the same name, what we specified in package.json. Okay. Which is, which is here. So go back to package.json. That's exactly the same guy. So that plugin name, what you see here is exactly the same. What is displayed over there? Okay. So we, we uninstalled it. So I want to make sure I install it back, right? So if I have to install it back. So I got to say Appium. Appium plugin, plugin install and the source as local iPhone iPhone source local location. Probably BWD. And Sini, why did you say local? Are there different sources that we could actually install this as well? Yeah. So since we are developing it here, we could install it from our local code base. And if we have released it to NPM probably people can use source equal to NPM and specify the name of the registry where they wanted to download it from. Okay. Sounds fair. Okay. Cool. So we right now, because we're developing it locally, we have not published it anywhere. We want to basically test it out, right? Okay. Looks good. So this clearly says that the plugin con demo one dot zero is successfully installed. Okay. So we have installed the plugin. Now we need to activate the plugin. So the way for us to activate the plugin is when you start your APM server, we basically call the activate. So you'll be basically call this guy. Okay. What basically this is doing now over here is which simply says APM server. Some command line arguments. Let's not talk about that. This is important for you to observe where we say a plugin con hyphen demo. So that con hyphen demo is your plugin name and you say hyphen, hyphen plugin. Okay. So that's the way you activate it. If a question is asked, can we activate multiple plugins? Yes. You just simply give it a comma separated and it's going to do that for you. Okay. Interesting. So now things to note over here. Right. So we have plugins. So it clearly says it's a con demo because you of course we activated only one plugin and the next thing to look out for for is your available plugins and it clearly says con hyphen demo is active. And if you see, I also have other plugins available like a gestures demo, a device farm, but they are not active because when we ran the server, we haven't specified the other available plugins with a comma separation. So here right now we are only loading this guy. Sounds good. So let's simply go and run npm test. And I actually have two emulators open for another reason. So but right now that's fine. All that we want to be very concerned is to see how the server logs are displayed to us. So you see it has started to create a session to us now. So we'll just wait here. Okay. So that's fine. We're not worried about whether it's a failure. This is passing failing, but we are more worried about the logs, right? Okay. So over here, you see that. So we have the plugin which can handle. This is the important part, right? So I'm going to turn this off. So it very clearly says that the plugin which can handle the command find elements and these are the stuffs we are in plugin find elements, driver info, arguments and stuff like that. And you see this very clearly says we are in the plugin find elements with a smiley, right? So that means the control has actually come to this piece of code over here, which is this. So we are in apium conf 2021 and it's pretty and it's come here and we have done the find element. And that's what even the logs are stating over here, which is where the logs are. The logs are this and very clearly says the plugin which can handle this and also if you see at some point, it will clearly state that that's a different one. Okay. That's fair enough. So that's the log what we were looking for. And you see when we put the logger, this is why we put the logger for. It says, you know, I want to use the confin Jane and those kinds of stuff. Okay. I think we have to rebuild now. Did we build it? Hmm. Did I build it? I think no. Yeah. That's a good catch. Probably it's taking from my oh, gosh, yeah. Cool. So I'm going to quickly build that. I'm going to uninstall what was there already. I mean, for this, we already have a helper where we put in things together inside our package.json. So I'm simply gonna use that. Basically, it just does all that bunch of stuff together. That's all as simple as that. Nothing fancy, so we're gonna do that. So it's gonna uninstall it and start the Appian server if I've shut the Appian server in the right manner. Perfect, cool, okay. So now I'm gonna run that just back again. Ah, no, I haven't killed my Appian port correctly. This is what happens with this terminal. That's fine, I'm gonna split it vertically, another one. That's good. So that's gonna be our test this time. So that's gonna be our build. So I'm simply gonna run my command back again, which is nothing about this. And am I in the right route? Yeah, we are there. So we could simply do an NPM test once this is completed. Okay, that sounds good. Quickly having a time check as well, that's good. So we'll do, it clearly says it's active. So I'm gonna open one of the invulators. Not this guy, probably this other one. Since it's running in background, meanwhile I will take up a question from Vidya Sagar. So do we need to install the plugin each time we restart the Appian server? So whenever we make some changes in our source code, we have to actually rebuild our plugin and then probably we also have to reinstall the plugin. And Jonathan was coming up with another hot reload option for driver, probably we will soon that, we will see that soon in for plugins as well. So you don't have to rebuild every time and then restart your Appian server. Yeah, cool. So you see, now it's fine. So you see the find element thingy, it clearly says the plugins which can handle the find element Conf demo is this. And we see it clearly returns that we are at an Appian Conf 2021 with a smiley, right? So that's the written statement. We simply printed that. And then the control goes back to, the default find element with a strategy, which we have given because we have given it to the next and next can also take it forward to the next clicks and et cetera, et cetera, okay? So that's about one part which Trini spoke to us. So we have done that. So we modified the find element and we straight away printed something and we gave the control back to Appian as well, right? So Trini, there was another one which you called out Trini in the slide. So you would say that we can write something which does not exist in Appian's base driver, right? Or something was currently not there. So let's see how to do that, right? So let's get a static new method map. And what do I have to add here, Trini, with the method map? Where do I? Add the Appian command that we wanted to create, whether it is of HTTP method, get, post, endpoint, detail, and so on and so forth. So see, I simply copied something from the route. So I said it's a get and what's the command? And let's say that get conf details. So that's the command. And I'm gonna simply say plugin slash conf slash get details or probably just say details, okay, nothing much to do there. Okay, so we have done this part now. So now I need to create a function to get some implementation out there, right? So you simply say async, put this function. So whenever this call is being done from the client when it comes to the server, this will get triggered and it comes over here. So here we should be, let's say that, so let's print seeing. Before we get there, there's another question from Ashwin asking, what is this new method map? So if you look at, I mean, a router.js, which Saiva is showing in base driver, which consists of a lot of methods that Appian currently supports. It has a definition, whereas the implementation resides in each platform specific driver. If you are going to the top, you could see something called method map. So what we are trying to do in our plugin is we are trying to add a new method and add the additional method into this existing method map in base driver. Yeah, I also see Jellips adding more points there. Thanks, Jellips. Okay, so coming back to this, so we just did that, right? But there's a problem here because when we look back at the architectures the way Srini said, right? So when anything comes to the Appian server, which comes to the new method maps because this is gonna get merged into our router.js. So which means either it has to get into UI automated too or it has to get inside XCUI driver or any driver, right? Let that be. But none of the drivers understand this specific endpoint because we are the ones who created that endpoint, which is plugin.conf details, right? So if a request has been made to any one of these drivers like UI automated to XCUI or any driver, any driver which is existing today in the world for Appian, they don't understand this. So because we are the ones who's responsible to handle this request, process the response out, right? So we are saying if a client is saying that, hey, give me details about this, you have to respond to this because sending this command to UI automated or XCUI, any driver, it doesn't make sense. So how do we stop that, right? So we have another function which is exposed which says should avoid proxy, okay? And that gives us three arguments, method, route and body. Method is simple, that's a get post, delete, blah, blah, and route is nothing but the URL, the entire URL. And body is if it's a post, it gives you the params, okay? So I already had something here to just to do it in a rejects way. So this should avoid proxy, the way the function itself is termed is looking for a written type as a Boolean. So I simply say this of test of route. So what we are simply, what are we trying to do over here? We are simply saying if a request has been made, which matches this rejects, which is plug-in slash conf, which is this guy, plug-in slash conf, then simply return a true. As simple as that, nothing really fancy, nothing very difficult over here. So once this returns a true, so now the plugin is telling the Appian server that, hey, you know what I'm telling, I'm instructing you, do not proxy this to UI automated or any other driver because they do not know this, I am the owner of this and I own it and I know what to do with it. So by sending this Boolean back to Appian server, Appian server does not proxy that and rather it lets the plugin to decide what it has to do over here, okay? So that's the console log, instead of console logging, let's say we want to return this, right? Because of course, if it's a test, we want the test to get this value out for us. So we definitely need a written over here, cool. So now that's done, so the implementation is all done, but how do we get this out as a part of our client, right? So as we are going to do with the client part, so that's the client. So we have a click and stuff. So how do we do this with the client? So the client has to send that. So we already have... Let's add a new command that we have created in our client code base. So we have click and delete session, probably you can add a new command with the details of whether it's a method, getPost and what's the endpoint that we have exposed on server side. So back to WebDriver.io now. So we have, they have exposed an add command function here, where you could specify the name of the command and the details specific to the command with its description and required parameters as well. In case of ours, the parameter is an empty, which we haven't decided to define anything. So we could add this command, which will eventually register the command that we have created in server back to the new method. I mean, back to the method that we have all of those defined. And we could call the command using driver.getConferenceDetails in our client, wherein that actually calls this specific endpoint in server and gives us back the conference details. Cool. So with that said, so Srinivas we run this, so which means this getConferenceDetails is going to get the response all the way from the plugin, right? So which means we have to see something getting printed in our test terminal, not in our APM logs. Keep that in mind, because we are not logging anything like we did with find elements, but rather we are returning a value to the client. So the client is getting the values out to the server. So let's do that, right? So that's our test, our server is still running, but we need to make, I need to kill this off and rebuild the server, right? To do that, so I'm simply gonna run npm build. And also call the installer. That's a plugin installer. Yep, that's gonna do a bunch of things which we already spoke. It's gonna remove the existing stuff, so we don't have to do all this like Srinivas said. So I'm gonna, and also I'm gonna keep my test ready here. Linking is doing, and then the server is getting started up, fantastic. Okay, so we get that. I don't know which humiliator is taking, so I'd rather open both. Either it is a white one, I don't know which order it's taking. I'm just keeping it up so that we know that the app's getting launched and things like that. That's a black one. Okay, cool. Should have to launch there. Okay. I have to interact with server, it's finding the element. Ta-da, you see that? So conference details, we are in the session build plugins. Where is that coming from? So this is not there anywhere in the client. The client test simply says driver.getcons details. Right Srinivas? Yeah, and we are sitting in the detail back. Perfect. Even you could see this message in our app in server, in our response actually. So, yeah. So this kind of gives the control back to client and the information that client needs to assert and you could do that eventually. And if you notice this as not like find element where you move the control back to the app in UI automated to server where it finds the element after you've printed the log here. In this case, basically it kinds of gives, I mean, plug in kinds of talk to espresso server. I mean, UI automated to server in this case and gives that control back to our client with the status for 200 and the information we are in session build plugins. Yeah. And you see the one which I've highlighted if it clearly says that, the plugin con details would normally be proxy. So would normally be proxy means what Srinivas said, but the plugin con demo wants to handle it internally. So we'll avoid proxying it in this case. So it clearly said that it's the plugin's responsibility now and the plugin will take care of all the stuff what you wanna do. Okay. So this way you can modify your plugin and also you can write new entry points into the plugin and you can do a bunch of stuff. So you don't have to depend on APM score module. You could completely decouple things and do a lot of stuff in this. So with this said, right? You know, when Jonathan came up with this idea of plugins and stuff. So there was one pressing issue which was always bothering the community. And of course, me and Srinivas being APM users for quite some time, it was definitely something what we have also seen is definitely parallel testing, right? So when it comes to parallel testing on devices, emulators or wherever that could be, it was always that you'll have to keep, you'll have to handle a lot of things at the client side because that means the client should be driver safe, the client should know what is the, you know, UDID that we need to send. There were a bunch of other attributes to keep in mind like unique port numbers, a device should free. There's a lot, right? So, I mean, with APM 2.x, with the plugin architecture, I mean, it was really cool for us, you know, we thought of this idea of solving the problem. So that no changes on the client side, no heavy lifting. So today, if you have a test in your client which runs in one device, you simply execute a plugin which we built, you activate the plugin which we built and the plugin is gonna take care of all of that. If you have like five test cases and all that, I probably is gonna do that. Srinivas gonna talk through all that. They like make the environment ready with the emulators and test and bits like that. So we will show you the demo. Switch back to slides. Yeah. You want to sleep? No, it's fine. We have a bunch of plugins that we have to author. One of that is device form. As I said, it's gonna help us build, it's gonna help us run our tests in parallel wherein it takes care of assigning the unique ports. In case if you are running some tests in parallel on Android using new automated route, you have to give a unique port called system port wherein it could communicate to your express or server running in your device. So finding a devices that are connected in your Mac post or Windows host, be it Android or iOS, it kind of takes the devices into its own pool and it maintains what is the state of a device. Initially the state of device is actually free because we are not running any tests in these two Android emulators that we have. We are gonna, it takes the state and maintains the state in path. I mean we're gonna maintain the state and assigns the device whenever we get request. Let's assume we have two devices here and we are gonna run three tests in parallel or four tests in parallel. So two devices can go in for two tests and the remaining two request will have to wait. So we are making a queue inside our plugin called device form wherein this queue will take, it will keeps on polling whether any device gets free after one of its execution. So if a device get free, then the device will get assigned to one of the request in the queue and it takes care of assigning the remaining request as and when the devices got free. So it also comes up with a handy UI which is kind of a glossy UI that we developed using GlassMorphism CSS wherein it gives you or lists you all the number of devices we have and which includes Android, iOS, platform specific, I mean platform specific device we could see that here. We have Android devices, both of those devices are currently running and if one of the device execution is over then it will actually make it free and it kinds of assigns the remaining request back to our, back to this. So you could see there is, there are two drivers. I mean there are two tests that got executed and both of these are running in parallel. There are other tests that are running as well but those doesn't have a free device. Until it gets free then it will be waiting for it to become free and all of those are internally handled by the plugin device form itself. And you see there are list of simulators that Psy has installed and currently is not running anything on simulators. So these two devices are actually busy and it lists down whether it is the actual, probably it's an emulator state, I mean emulator or a real device as well. And it kinds of gives more information as well in terms of what kind of battery state all of those which is something in our backlog that is something that we haven't released yet can subdues the battery percentage of device, CPU percentage of the device or real devices that we have. So it maintains a queue state and then assigns the device that are free and it does everything and all you need to do is just initialize the plugin and we are good to go. So Srinu you got five minutes left. Cool, thanks. Yeah and I would say people to go check out the device farm and other plugins what we have probably you could give it a shot and give feedback so that we could make it better. But this is something which is, yeah. Yeah, as like Appian 2.0 is in beta, we are also in beta and feel free to try that out and give us feedback so we could basically improve the plugin and we have to come in again. Plugin is already open source, feel free to have a look at it. Cool. And all of these, I mean the plugins can also have certain configurations. If you wanted to run on your iPhone, you could run it on your iPhone though you have other Android devices up and running. If you wanted to target only on iPhone or if you wanted to target on your iPads and latest for example, you could do that also as well as plugin. And we were doing this previously as well using a client side. I mean we have a Maman project called Appian Test Distribution but all of those are translated back to our Appian plugin which is very cool. So any, for example, we have demonstrated now this web browser, we could do this on any clients for that matters. Yeah. And I also see most of the questions answered by Jonathan. Thanks a lot Jonathan for sticking around that later and helping us answering those questions at the chat. I randomly see one question Deepika has asked like parallel execution between iOS and Android at the same time works the same. Yes, you're right. We could execute both iOS and Android at the same time and the test can get queued and get distributed but there are certain things like certain flags that we can also set where you could configure saying that hey right now I only do my cloud has got both iOS and Android but I just wanna run on iOS so you could also configure that based on arguments which can be sent through the plugin saying that it's only Android only, iOS only, iPad only or both and stuff like that. So there are a bunch of these configurations that can also be done. And the dashboards also getting improvised or where we are also coming up with to show the test cases which is running in your real devices or emulators onto the browser like more like mirroring them so that when you click on a specific device card it can also bring up your device screen to say what test is currently running and also give you more on informations like okay, this specific device ran these test cases. So these kinds of more stuff we have in backlog to make this plugin more useful to the community. With that said, probably we can quickly jump into I'm gonna run through very fast on the summary. So we did create new routes we overrided the modifying existing APM commands. So we created a new endpoint called get config get config details and that's a new route and we modified the find elements there. Step number one, keep in mind in your package.json you need to have a dependency under dependencies you say APM based plugin and then under and the second is keep an APM node with your plugin name and main class and step number two, very simple you create a class called as exactly the same what you mentioned in the main class which extends a base plugin and then you override what do you want to do there and by adding routes, new static map so whatever you add inside new static map simply gets merged into APMs or route.js and any call from the client like you say driver.getfig data any call from the client simply comes in and because this route is already managed and mapped into route.js and we have also told APM that hey do not proxy to any of the upstream drivers because it's a plugin's responsibility so that was taken care and then the getfig session data is executed and whatever you return gets returned to the client and we did see how we can install and activate these plugins there are multiple ways that you could do APM Pro has got a good staff and me and Sriniv also put down certain articles with APM tools featuring APM tools take a look at those blogs which can give you more details about how you want to install and a bunch of other different ways that you want to install these plugins and some of the plugins that we have right now which we found out was these some are maintained by APM devs officially an APM weight plugin device farm gestures are something what me and Sriniv have featured at a very early days keeping up some ideas of how you can build a framework or a plugin and they all have links so when the slides have been shared with you you will definitely get to click on these links to go through and on time thank you so much for sticking around thank you guys thank you for joining us and thanks Jonathan thank you thanks Jonathan yeah and Sriniv thank you so much for sharing your your knowledge and expertise and helping people get started to build a driver