 All right. Hello, everyone and welcome to the nuts and bolts of web. I'm excited to have you all here for this workshop. And I'm really looking forward for the next two hours. I'm learning everything about rep and how to use framework and how you build up your test automation framework from zero to infinity. Before we get into the nuts and bolts, let me introduce myself. I'm Christian. I'm a software engineer in the open source program office at Source Labs, where I work on various of open source projects that are related to testing and test automation. I'm also helping out in various of ways to help the company to be good open source citizen externally as well as internally. And I try to support and help out the WPC working group in creating the new stack for the web fair protocol. Our agenda for today looks as follows. We have an introduction part, which is going to be a presentation of me that I give on web.org. And there will be a hot hands on workshop where you can already go on the website, get up.com slash Christian, my informant slash rep.org minus hands on where we have a variety of tasks that you can follow along that help you to understand the framework and, you know, the knits and bits of it. If you have already experienced with Reptile Valeo, you can skip the presentation part and, you know, have it in the background and already start working on the workshop. I think there's enough material that, you know, can keep you busy for the next couple of hours. And so if you're already familiar with Reptile Valeo, if you already heard the presentation or seen the presentation, free free to just skip and work on the workshop and we will come back to it after the presentation where it can then help individual people out in the chat, where we also have a couple of members of the web.org project with questions and answers. So let me get started with introducing Reptile Valeo for everyone who has not used it so far. And before we, and if before we want to do that, I want to step, take a step, take even one more step back. I want to start with explaining the web.org protocol in general. The web.org protocol is a remote control interface that enables introspection and control of user agents. What does it mean? And there are several words that are important here. First off, it says it's a remote control interface. That means that it is some sort of contract that allows you to, you know, do certain things with that protocol. Then this protocol enables an introspection and control, which means this interface that the web driver describes allows you to introspect and control that user and that something. And at the end it says the introspection control of a user agent. And that means a user agent can be everything that has a display can be used by a user. That is not only a browser that you would normally use. It can be everything from, you know, a console, a PlayStation, a phone, a tablet, anything that can be used by a user can be controlled, theoretically. So the way how this protocol looks like is as follows, we have a set of rest endpoints that allow you to control and introspect a browser. You have rest endpoints that allow you to create a browser session. We have rest endpoints that allow you to visit a specific URL and to do various other things. To trigger this action in the browser, you will have to call this URL. And the reason why this was created this way is it allowed everyone with any programming language that, you know, supports sending a GP request to implement the web portal protocol. And therefore we have these days a Selenium package for almost all languages that there are outside. So the web portal protocol is WPC standards for browser automation. And this is really important. All browser vendors are working together in building out the standard for automating a browser. That means that every time you automate a browser you will have the same results running the click command on Chrome or running the click command on Safari. It will be always the same. You might have heard about the JSON wire protocol before, which was the predecessor that now since we have a WPC standard is not valid anymore. The web portal protocol is not Selenium. Back in the days where the Selenium project really contained all the drivers and all the implementations of these drivers, pretty much Selenium was all what is for browser automation. But these days it is nicely abstracted into an external protocol that is developed by a standard organization. And then there are a variety of implementers that have implemented a framework on top of WebTiger, which is for instance Selenium or WebDivio. As I mentioned before, it defines the rest interface so you can use and implement this protocol for all languages. And it's a common denominator currently for cross-browse automation. You might have heard about Appio, which extends the WebTiger protocol for allowing mobile commands, but the WebTiger protocol itself as it is right now is focused on browser automation. And as mentioned, it can be used with all languages. The setup that you usually would have if you run a task with the WebTiger protocol is that you would have a simple test script or a test script or an automation script that you have written with Selenium or other web-diver-based frameworks like WebDivio. And this framework would then send HTTP request to something called a driver. This today almost for every browser a driver that allows to control and inspect the browser. It works similarly for mobile where we have Appium that allows you to simplify the mobile automation across iOS and Android. The drivers in itself, which are developed by the browser vendors have all the knowledge to trigger a natural event in the browser, which is different to tools like Cypress that only can emulate these events. So as I mentioned, you can literally automate every user agent. One of my projects in the past was to automate and rep application on a smart TV using Appium, which you can see here in this video. So you can technically, if you have a driver, implement the protocol for that specific IoT device and have rep driver be able to automate it. For cloud-based vendors like Boss Labs, their value proposition is easy, right? Instead of having to set up all these browser drivers for you and having to keep up with the browser updates, there's these browser vendors that just do this for you and they provide you one HEP endpoint where you can just create a session for the mobile device for a browser as you wish, and they provide you with useful additional information like screenshots, logs, and performance information. Let's get to WebDriver in more detail and start with the really key features of the framework. One of them I want to point out first is the easy test setup. WebDriver provides a configuration wizard that walks you through a common setup step to create your configuration file. This allows you to simply get up and running quickly with just a matter of seconds. It also provides various of services that allow you to deep integrate into third-party vendors like app tools for visual testing, where services enhance the browser functionality and the browser interface to just simply interact with a third-party vendor. Another example for that is the source service that just simply allows you to start this job on Source Labs and just some configuration in your config file. What's also great is that we have a lot of tutorials and learn material. There's a website called Learn with WebDriver.io where you can currently find a lot of videos for free to watch and learn, but there's also a channel built by one of our team members Kevin Lamping who has created so many great videos on WebDriver.io and there's other contributors that have a lot of WebDriver material as well. One additional really awesome thing about WebDriver.io is the community. We have currently almost 6,000 people in our support chat which help each other out on daily basis, so if you have a problem using WebDriver.io, if you run into a bug you can always find your help there. And last but not least WebDriver.io is a project that's not owned by a company, it's owned by the AWS Foundation. That allows us to, this foundation helps us to scale the project in a healthy manner, create, get new collaborators on board and work together with projects like Node.js Webpack, Express or AMP to commonly improve ourselves throughout the projects. WebDriver.io can essentially be used in 3 different modes. There is the bare metal mode I would call it, the standalone mode and the WDO test runner mode. The reason behind these 3 different layers is because we wanted to make automating a browser or mobile device as modular as possible. With the bare metal mode that you can use with the WebDriver.io MPM package you pretty much get direct access to the WebDriver protocol. It exposes all the methods that WebDriver protocol provides as an interface and allows you to just use the protocol in a programmable fashion. The standalone mode then enhances that functionality by creating a bunch of commands on top of it that help you to do simple interaction and common testing interactions with your application on the test. Last but not least, the WDO test runner then provides you a test aspect to everything around browser automation. You can automate a browser and test certain conditions in it. Here's an example using the bare metal WebDriver package where you have a navigate to command, a find element command. If you find an element you need to know what the protocol returns in order to access, for instance, the element ID. This is sometimes not useful if you want to write an extensive test suite because you don't want to deal with low level protocol primitives. This WebDriver package definitely helps you if you want to build a new framework that looks a little bit different than WebDriver for your community. There are examples like Spectron, who is the test framework for Electron, that has used this capability. The WebDriver project, as I mentioned before, makes interacting with the browser a little bit more easier. As you can see here, the commands are a little bit more shorter and there's something like an element object where you have to fetch an element to explicitly call element-specific commands on it. And then last but not least, there's a test-runner mode where you can run WebDriver command in a test context where you have an id block that allows you to assert the amount of elements that you find on the page or where you can receive a text of a certain element and assert against that. Since version 6 we now have a custom assertion library that is built on top of so you already have an assertion library integrated and ready to use. To get started with the WDO test-runner, which I think is the common usage of the WebDriver framework, is by installing the AdWdo CLI package, which brings you all the capabilities in your command-line interface. We have a config command that helps you to configure the WDO config file. We allow you to install services and reporters into your config file automatically. We have a REPL functionality and, of course, a run command that allows you to run a test to. Everything around the WDO test-runner goes with the config file that you use to run your test specs. This config file exposes all configurations and options for your specific test-run. These configurations can include things like the specs that you want to run, which specs you want to include, the concurrency that you want to run your test in, the capabilities that you want to run your test in, and all these things. It is really important if you build out a large test suit that you have multiple configuration files for different environments. For your development workflow, you want to specifically run just one browser like Chrome to make sure that your end-to-end test pass. But for staging or production test, you might want to tweak that configuration a little bit so you run it on more browser to create and get more coverage. The really best case scenario that you can do is you create a common WDO config file and you enhance that config file in a new config file. As you can see here, I have a WDO source.config file, which I use for my staging and production test, where I run multiple capabilities and where I include the source service, which I don't need for development purposes. Test-work works that are supported with RepaVero, Mocker, Cucumber, Jasmine, and Jest. Jest has a little asterisk in there because we don't have Jest integrated itself, but the test that you run with Jasmine or assertion library look like Jest's test. Next to the frameworks that we support, we always have various of reporters that you can use, like spec.allurej, Unity, CDTAP, Mocker, Awesome, and we have a bunch of services that allow you to integrate with other third-party vendors for services like Source, Appium. We have a plugin that allows you to start a static server to serve your web app. We have services for drivers and the Selenium standalone server and a lot of more. With the reporters and services, you can create your test setup really individually that is suited for your needs. What services are doing are essentially they are allowing you to introspect the lifecycle of a test. They allow you to create a bunch of hooks for a specific scenario, so specific lifecycle events like before a session starts, before test starts, before a suit starts, or before a command starts, as well as after all that. It allows you to do asynchronous operation on top of it. That allows us to start servers or start a MySQL database if we need to whenever we need it. It also provides a nice way to encapsulate configurations and encapsulate complexity out of the configuration file, which makes it really plug-and-playable. A lot of these services already exist on NPM and there's a big community that creates services for you, but you can also create your custom services along the way. As an example, I want to look like because it allows you to do to run Chrome DevTools protocol commands while running tests on Chrome. The way how it works is you have a webdiver session as normal using the ChromeDiver binary and at the same time with that service you can run a CDP command and, for instance, listen to network logs or do various other things that the Chrome DevTools protocol provides you. For that, I want to show an example so you see here my IDE hopefully. I have an example in the directory where I have a test that enables the network. It runs a CDP command to enable the network interface in Chrome DevTools and then literally just listens to events that is happening in Chrome. So what I do here is I open the Google website and at the same time I listen to whatever requests have been loaded and you can see nicely the first two commands are based on the Chrome DevTools protocol while the second is the WebTuber protocol and they can nicely work together. So let me get up my console for a second. Well, this way we can do it. There we go. So now I'm having open my terminal. I go into the example folder for DevTools and I'm going to run the service with that specific network test. So what's happening now is that there's a Chrome driver running, opening Chrome for me, going on the Chrome.com page and it just opens and closes immediately but you can see here in the console alerts you see all the network commands that have been intercepted and you can based on that have tests that check that if certain URLs have been called, if a certain request has been made and a bunch of things more that you can do with the Chrome DevTools protocol map. Going back to the slides. There are of course more features. We have a bunch of nice selector strategy extractions that make it really simple to fetch elements. You can of course use with the simple dollar sign command fetch CSS selectors. You can, by starting with two slashes, you can use the next path. We have ways, if you start with an equal sign we look for a link with that specific text but you can also just look for any HTML element that has a specific text or contains a specific text. So that really makes it simple to find the element that you want to interact with. We even go a little bit more deeper where we want to support native frameworks as many of people use like React where we have a React dollar sign command that allows you to fetch elements from a React application based on their component name and their state and their properties which is really useful. And we have also a lot of selector strategies for mobile where you can select specific iOS selectors or Android selectors using the UI Automated Framework as well as allowing you to simply access the accessibility ID with a tilde sign. Another nice feature is the custom commands. WebDriver is extendable. You can create as much new commands as you need to. So this example is actually from a real project that I had in source where I wanted to use or interact with the rest interface without having to do anything with the browser. So I created a custom command that would do a post for me to delete a specific user and in my test I could just call this command in a synchronous fashion which made it really simple for me to stop users and just test the specific thing that I want to. WebDriver has a concept of multi-remotes so usually you have one single browser and one test file where the browser just follows the instructions that are in your test file and you get the results. But there are scenarios where you need multiple user agents to test a certain scenario. If you have applications that have a chat application or if you want to test a webRTC application where you need two parties to actually work with the app you can use the multi-remote test. And that allows you to control multiple environments at the same time in one single test. Let's do a little theory about the PageObject model. You probably already have heard about it and it's a really popular framework that helps you to write scalable test suits. The PageObject model is itself a design pattern that became really popular. It keeps your testing code clean and easy to maintain as you abstract all the information about the specific test away from the test itself. And that makes it really easy to extend functionality to a specific page and keep the test clean and reusable. So in an ideal world where you let's say redesign just redesign the complete page all you need to do is to change the selectors and some methods of the PageObject model and your tests can stay the same. This really helps you to scale out your test files and make your test in self less brittle. Here's an example of how you can use the PageObject model in Repdivio using JavaScript's getter functionalities which would then return an element and functions to do certain interactions with the page. This results in a really clean test where you essentially just interact with the PageObject model instead of selectors or specific elements in itself. Right, a demo is worth more than a thousand words. So let's jump into a couple of demos that I've prepared that show what Repdivio is capable of. And let's start with multi-remote. Going back into my ID, I have an example folder for multi-remote where I want to test a chat version that is demonstrating Socket IO. In this test which I run with two Chrome browsers I have the ability to call a certain command like opening the website on browser at the same time or just run the command on one browser at a time as you can see here. This allows me to log in both of the parties and enter the username and allow one browser to interact with the message of the other browsers. So you'll see that we log into Socket IO's chat and someone will say, hey, my name is Edgar and the other message tries to find out who that person is and will say hello other person, how are you today? So if we want this, then let's test the chat. We will see that there are two browsers spinning up. One is called the A, one is called the B, says hey, what's up, my name is Edgar and the other one says hello Edgar, how are you today? Another example as I mentioned is the RepRTC example which I have here where I set in some Chrome options to fake the media stream and then I just open the RepRTC channel and see how that looks like. So again, two browsers spin up for my test and they join a random channel and that's about it. Going back to the slides, the next demo is performance testing. Last year I really worked into how we can integrate performance testing that you have for instance with Lighthouse or WebHTest.org into an actual automation script and for that we have built a service, the DevTool service I mentioned before which has these capabilities now. So you can call a command called enable performance audits and it will automatically flutter the CPU and the network for you to kind of emulate a mobile device and with that you can create, you can receive performance metrics like first meaningful paint, first interactive of the speed index or test the overall performance score. The DevTool service here uses Lighthouse under the hood to get you all these metrics. So let's test that out. Actually we should open our test page. It needs to be booted first. Oh, it's already there. Perfect. So we cannot just go and say into DevTools folder back the chat that we have with metrics. So what's happened here now is that it opens a browser with mobile capabilities. So the page load is much lower because it's running on a regular 3G connection and now it takes, it does performance, it captures the performance of that page and allows me to set against it. So as you can see here, without me doing anything, the first meaningful paint was at 3.7 seconds and I expected it to be less than 3 seconds. The same was first interactive and this made my overall performance score to 78% which I expected to be at least above 92%. So this allows you to integrate performance, Lighthouse performance scores into your automation test. Next step is visual question. Therefore I have this demo. As I mentioned before, you whatever provides an app.ly.tools.service that you can just integrate by installing the app.ly.tools.service npm package and then all you need to do is in your configuration which I have here, say that I have an app.ly.tools.service installed and here's my app.ly.tools.key and it knows everything what it needs to know about creating the screenshots and checking to it. So the service creates a new command called take snapshot and it will take the snapshot of these two pages. So if we run this npm1 test local, it will run the visual test and the service formats the window size and then opens Google and takes the snapshot as well as it makes a dome snapshot and after entering it it takes another screenshot on the second page to see if the result afterwards is the same. And I already see differences because I did not really clean up the baseline but what you can see is that without having to deal with the app.ly.tools.app.ly or anything I can push up my test that I have just run two app.ly.tools automatically without doing anything which is really great. And last but not least is the watch mode. WebDub allows you to watch files as you work on them. So what you can see is what you can think of is you go to the office in the morning and your first task of the day is to start working on npm test for your project. And what you can do you have a test project with tests. And so what you can do in your project is just say npm1 watch which runs the run command with a dash dash watch parameter. And this will create all the tests. In this case these are headless tests in the source cloud as I want to have these tests being really fast and return the results quickly. I have these running with high concurrency there. And you can see that it fairly runs quite quickly. And the nice part about the watch command is that it doesn't close down the session it will keep the session open. So whenever you do a change a console a lock and you press save it should rerun the test essentially. Let me see if this test is actually not running if I do it here. There we go. It immediately runs the test and gives you results in this case inferior because the test has fit. You can also make a change in your overall location and then it automatically runs all the test files for you. So you can see here without having to re-spin the checkbox up and it immediately gives you feedback about all your tests in the second. And that's almost about it with the demos. So as you may recently heard we have released a new major version which is version 6 which is not that difficult to upgrade compared to version 5 if you have to go through that. The new version now comes with the Chrome DevTools protocol embedded. We see that the Papatier project is getting stronger and stronger and supports more and more browsers. So with that we want to leverage on that and with the version 6 if you install Web.io you don't need to have a browser driver anymore to start testing on Chrome or Firefox and idly right away. We also embedded a library into the test-runner project called expect-reprovial which gives you all the nice assertion measures that we have with frameworks like Jest in your hand for end-to-end testing purposes where you have a 2B display assertion to make sure that the element is displayed or not. And the assertion itself also are really smart because they have specific rates that help you reduce the play games in your test. We improved the performance of the core packages in general. We reduced the speed how elements can be attached. We also reduced the bundle size and we want to prepare to allow Web.io to run in the browser. And the most important part about version 6 release is that we dropped support for Node version 8 and we announced that we want to keep version 5 a long-term supported version because we know that a lot of people had to struggle to go through the upgrade and don't want to update again right away. What comes next? So we have a big world map ahead of us and we're really looking for anyone who's interested in helping us out here. There's a bunch of things that you can help us out and support the project with. We're planning to build a fiddle application for Web.io where you can share your test snippets with other people and allow that to run in that fiddle application. We're currently working on a better support for networking and mocking. You find the proposals for these features on GitHub and they're already really exciting. One of the great things that we want to do is we want to allow to make snapshots of the network request so we can easily check if the white network request has been made or not. Then we want to simplify the bootstrap mechanism allow you to not only configure your configuration file but also create some sample test files for you to get started and of course we're always looking for better documentation and examples for everyone to easily get started with Web.io. The best way to get involved is to just go on the GitHub project page look through the issue list and look for issues that are labeled with good first pick or first timers only. These are really made for people that want to start working on Web.io and they're really well explained. Don't hesitate if you have questions around solving that issue. We as collaborators would really like to help you help us out. With that said this is the end of the first part of the workshop with the presentation. If you have any questions on the presentation itself now's the time to ask these so I can go back into the slides or I can show you the specific examples and if there are no questions we would go forward to the actual workshop on the GitHub page. Does anyone have questions on the presentation or already on some of the things that were in the hands-on material? I see so far no questions. If you have questions feel free to just write them down in the chat. We have a bunch of people watching the chat and they can help you out with some specific things if they are unclear. For the second part of this workshop let's go into the hands-on material. We have a bunch of chapters that are built on top of each other where you start setting up an environment and build your first automation script in standalone mode then move on to the test runner, include your own reporters and services and so on until some more time you can start by using the DeafWords package or doing visual regression testing. Let's start with the first chapter. The objective here is to get an environment running where you can use WebGov. For that of course you need Node.js installed I would recommend to create a new repository that we can do. Let me make this bigger and make this over. Let's just create a workshop folder. It's not existing. What you need to do with the first chapter is to get a driver from the Chrome driver page, from the edge driver page where whatever browser you prefer start the driver and run a WebDriver script. Let me work through this. We need the driver in the first place because WebDriver pretty much just defines certain endpoints that you can call with your framework and it leaves it up to the driver to execute that action in the browser. This driver is developed by the browser vendors. The browser vendors know exactly how to make a certain action happen. This way we go to the download page of the Chrome driver project and we load the latest Chrome driver version for whatever Chrome you have installed. You just unpeg it, unzip it and have. If you have Mac, make it globally available so it's easy for you to run it from every browser, from every environment, directly where you're in. I have a Chrome driver command available for me by just extracting Chrome driver and moving them in one of the directories where I keep all my custom binary files. Binary files for Helm, for CACO driver, for Tiller and for Chrome driver. I have Chrome driver version 86. All I need to do is to start Chrome driver with a custom port, let's say standard on 4.44 which is not existing. This port is already used by something else which I will clear up. There we go. Now Chrome driver is running on port 4.444 and I create now a second console that I want to use to write my webdivero script. I go into my workshop again and I install webdivero which should not take that much time. And again, always if you have questions through the workshop in other chapters feel free to just put them in the chat and I can help you out. So here we have a workshop, we have installed webdivero. Let's write a simple script I actually used my IDE for. So I have a new file called index or test.js where I import webdivero by saying remote, again in the remote property. You can create the same session with multi remote by just using the multi remote property function. So then I use I write an asynchronous function because I want to itself invoking asynchronous function because I want to use a single write for creating all the tool for running all the commands. So here I say my browser awaits a remote session that's wrong, waits a remote session and as you can see here we have typescript support or we have general typing support if you use the S code and similar IDs but webdivero also calls with typescript support definitions so you can use typescript if you want to. So my capabilities are since I have Chrome by running it should be Chrome so I can say Chrome and that's all I need to create a remote session on my local machine then I can go ahead and say browser.ul and I always like to use the json.org page as my guinea pig and then I can say log me the title of that page and at the end we turn with delete session. There we go. That should do the trick as you can see here this is a self invoking asynchronous function so I initiate the function and immediately call it and it's an asynchronous context so I can use the way in it and everything goes right I can call the test.js file and it now uses Chrome driver to open json.org really quickly and close it again there we go. Yeah and just to show you was wondering where I think I've still a Chrome driver process you love running so let me find that one. No so I've closed all my Chrome driver sessions so we have no driver running now and I can still run WebDriver without that driver because it now uses Puppeteer under the hood and the DevTools package to run the same commands using the Chrome DevTools protocol so here you see that Chrome launches with some default flags and then it detects the Chrome DevTools port and uses Puppeteer moving forward to just execute the same commands. The same would also work with Firefox 90 and soon with the stable version of Firefox which is exciting. Okay this is all I think we need to do for chapter one. Let's go to chapter two. This chapter is about writing an automation script that uses an actual application in this case the view to do MBC app and what we want to do is to run ChromeDriver as we've done before and do I think create three items yeah enter three items into the to-do list mark a second item is complete and print out the amount of items left so let's work on this. We can reuse our existing script here so what we do is we want to go to the to-do MBC app then let's do this there we go there are already three in there let's clear them all clear. Actually what are the items I like to use the DevTools application to just find the items for me so in this case it looks like we have a class to-do list and it contains various of to-dos so let's fetch these cons items equals weight browser dollar dollar sign which fetches multiple elements the one dollar sign fetches one element the first one at times the dollar dollar sign fetches multiple elements so from the to-do list we want to find all the to-dos that are in there so this should give me an array of three elements and one of the task was to click the second element so what we can do is we say weight items the first element so it's the second to-do and then we want to click on it as you can see here items number one or the first entry of the items contains an element object which in itself has things the commands we just did that you can use to click to get the text or various other things so we have we click on it and then we want to see how many items are left this is hidden here let's find this element it's the list the first no to-do count strong so what we do is after we click on it we define a new element that says weight browser dot dollar sign to-do count and in the strong element and then we just log it out I think that was the task print out exactly so log out items left which is an element and an element as you can see here in the documentation under our API you see all the commands that are available for the browser and all the commands that are available for an element and to get the text of an element we use the get text command here dot get text can remove that and this should almost do it let me add a pause an implicit pause in the middle or at the end so that we can see that actually everything is happening as expected and that looks so far good to me let's try this out so run the same script again it again runs on the dev-tooth package but like I said it shouldn't should not matter but it fails in this case so let's before we look into that let's just use Chrome driver so I can use the web-tooth code where I expect everything to work note that error was intentionally okay I think I've seen the problem it says cannot we click on undefined so if you have such an error always check what you called click on and here we see that items 0, items number 1 is undefined and I assume that the reason for that is that the elements once I fetched them have not been on the page yet that happens and to avoid that it's always good if your app is dynamic and loads things from the back end where you never know when the elements appear to have an explicit weight to it usually that happens automatically but if you're dealing with multiple elements that is difficult to immediate automatically so what you do is you say so first wait for it to exist until before I click on it so you can close this I think and this as well and so now we run this again and check if it works again wait for it to exist undefined this is a nice example so there's apparently nothing in here so let's apparently items 0 will return nothing so what we can do is we wait for the first element we've just fetched the first element of it so let's say first element browser.$ so let's wait for the first element to exist and then we fetch all the elements and click on the first one there is 100% a more cleaner way to do this but this is my solution that I will use for now let's see if that works there we go of course cannot find any to do because I don't have any I went one step ahead because we first have to enter three items let's do this first then so we can remove this because once we enter items we should already see them so I need to find the enter input element which is going to be the new to do and let's define that const new to do equals the new to do we wait for the new to do to appear so when we let the application do its thing and wait until the element is there so we say wait for exist and then we add a new value to it and we can do two things we can either add a value to the element and hit enter and we can just use the keys element to just enter keys to the current focus element but what I will do is I say wait new to do add value and I input two values to do number one and the second one is enter and we recognize that this is a operation system input so it will not right enter out into the input field it will just hit enter as button so let's try this to do one, two, three and then I should have three to do, click on the first one and then we'll see what happens there we go, we results let's do another wait I'm not sure why it did not wait because I didn't did a pass there so it's always important every command is asynchronous so you have to deal with async-await if you use the standalone mode if we later move to the webdero support to the webdero test runner we can always move the async-await because this is handled by the test runner so let's run this again finally with the results adding three to do I did not because I did not click on the on the bottom here on this check mark so in the to do we have an input called toggle which we need to click for that so we accidentally clicked on the to do but clicking on the to do will not change will not mark it as complete what we need to do is we need to find the toggle so we say find me the toggle within the first to do so we can chain element calls and like here so that we find elements that are within that element so here I want to find with the class toggle within the first element of the to do and then toggle.click should do the trick see there we go and finally results and with that we completed the second chapter there are some additional things that you can do here for instance running the same using the package or even better modifying the local storage to insert already existing to do into the application so with the command you have access to the local storage which is the reason why when I reload I already have these items here the defaults to memory application local storage today I received you see here my to do is that I stored in this local storage and you can imitate and mark the local storage with the defaults protocol and use running on the defaults automation protocol you already access to these features you can try to run this and try it out for yourself and see if you can get this running without having to enter all three to do is first but we will move ahead we have one hour left, half an hour left in this session to go to chapter 3 does anyone else so far has questions I still see a crate chat anyone can report his progress where he is still here we will then move on to this third chapter where we introduce wdo test and for this chapter we want to create a config file, a test directory for our end-to-end test files we want to report the test.js code that we have so you run in the test runner we want to make the code asynchronous and remove all the asynchronous weights and use our embedded description library and create a simple entry script for our npm package so let's do that to get started with the web-to-world test runner we need to install it say npm install at wdo cli and this installs the cli locally to our project make sure that you should always install such a cli locally to avoid confusions with a global install cli tool that has the same name so you can still access this wdo command with the mpx helper so if we call npx nwdo we get the latest version of this cli and some documentation around it so to create the config file now all we need to do is to call mpx wdo and it will ask you do you want to create one so in the next chapter all we need to do is just testing everything on my local machine running it on the cloud vendor will come in later so we say I want to test on my local machine I like Walker to run my test in I want to run my test synchronous my tests are located in test specs and so on I currently don't have Babel or currently don't use TypeScript I want to use the spec reporter but there as you can see various of other reporters that you can use I want to use the Chrome driver service so I can get rid of this Chrome driver and wdo takes care on creating the Chrome driver for me and start creating this Chrome driver instance for me so my PACE URL is still the same to do mbc and it now installs all the packages that are necessary for this specific setup for me which is good and it automatically adds it to the package.json there we go now we can run essentially wdo already but before let's create our test file as we have set in the configuration wizard our tests are located in this directory so what we do is to create a new folder as say test in that folder we create a new one for specs and in that we want to move our test folder so now we have a script that is supposed to be a test so instead of importing we don't need to do that anymore because the test runner creates a session for it what we do is we just write test files from now on let me comment this out so describe to do mbc and this describe block has no the hook that opens for me the page where I want to go to so browser.ul and then I have an it block that inserts three items and for that I will copy this part so the advantage now is that the Chrome test runner by default runs the commands synchronous it uses the fibers package to plug into the node internals to make this the promise calls of every command is synchronous call which you should not do for any other reason than that for testing it's not important that the event loop stays still for a while because you're essentially testing the user load but you should not do that for serving web applications or any other node JS applications so we can remove the AC and the weight for the commands we can also move the browser dot for every dollar command that we write because this dollar command is global now as well and so this makes the test even look simpler than before no single weight and no long commands just a dollar function as we had it years ago or still have with jQuery so we're entering three items and now we want to let's check immediately the amount of items because I expect now that always does it it's back now that all items so all to-dos to have actually I don't know this one let's look into our search library okay to have children there we go here's the assertion for this and it would be this assertion our element is the to-dos and we expect them to have children equals 3 so let's write this part of the test we have our config file it has my capability chrome it has my base well so by having a base well I don't need to write this URL anymore I can just say it sets some time out it has a Chrome driver as a service setup we use mocker we have a spec a spec reporter and a bunch of other hooks that we can also use as part of the config file alright I think we have all we need to give it the first spin so all we need to do now is calling npxw.io again and by default it runs the spec that you have and fails for okay let's just write this down interesting that fails expect it to receive function interesting okay it points to my tests here describe before okay yeah that was I was always you know what's going on apparently my VS code has imported this describe which is not correct I'm sorry about that so let's go ahead alright so it starts the MVC app but not the right page this is not the right page and you see it tries to find the new to-do item but it still tries to try it multiple times before it automatically ends up doing a failing on you so actually here you just see one call command but what happens in reality is that if the command the element does not be found it tries to try some multiple times we also wait for it here in the second line so this happens anyway let's see what's our base URL is it's this one so essentially this should work I see it because it concatenates the path is we should I think write it with a dot otherwise we will start with the to-do MVC base page so let's concatenate it this way and try this again now we are there I think that's it's failing because it waits for three serializes the same string ok let me see what we got back it could not find the elements so let's go back into the code so this should be equal three I guess we just want to quantify this and say the links of all these elements to be three I guess this way of is sorting or matching the amount of elements doesn't work so just say dot lengths to be three and this should hopefully work there we go now we can rewrite the rest of the steps and we can say mark the second item as complete and here we just copy this code uncommented so again we remove the weights from it and so we have all items we find the first item and click on that item that still works like this now we can remove this one as well as this one because dollar dollar dollar sign are globals and then we get the items left and from that get text we should out of this we make an assertion so we say expect items to have text let's double check this our assertion library has a matcher that is called to have text it's right here so all you need to put into the expect is the element and just you call to have spec on it and that's about it we can remove the rest of the codes because we also not need to clean up the browser session that's happening by the test one as well let's run this okay now with my bet we have to expect items left to have text to because right before we checked if it has no text we want to make sure that the text says to there we go and there we go but as you can see before it tried to fetch the text of the element go back try to fetch where was it one more yeah so we tried to fetch the text of the element multiple times and this is part of the advantage of using the web divero assertion library it has these retries in the assertion which will remove the flakiness of your test if your element shows up later or if the re-rendering of the element takes a bit time okay this with that we completed chapter 3 I think there's also an additional step for it but I think so far it looks good and we can move on to chapter 4 before that I will have a look into the chat it seems it's still very right there we have still 35 minutes to go so let's just continue again if you have questions so if you have questions working on one of the chapter please let me know in the chat let me wave to you so let me know and we can help you out there so I will move to chapter 4 here we want to use the task is to run Chrome Devices Service which we already do automatically we want to have the allure reported to the list to the reporters then we want to use the allure CLI to generate the uncompleted to report in the uncompleted and we want to report the Chrome driver logs into the logs directory and we can see what's going on in Chrome driver and see where Chrome driver struggled to fetch elements and so on so let's first add the allure reported to our reporters list what we need to do is as I mentioned before we have an install command and one of them is the allure reporter so we can just copy this out npx let's reinstall addwdo slash allure and automatically adds that allure to our reporters list which is nice so there we go and we want to use allure CLI to generate the allure report in the uncompleted so the allure reported just captures information from the test to get the actual allure html page we need to do a little bit more so for that we should look into the docs and the docs have some information about the output here and I just will take this one to set a specific output here so to apply properties to a reporter we wrap this into an array and put in some options in there and then it should use the command line tool over here and we need to call the generate command on it as you can see here let's skip that for now let's skip that task for now and just run this first the Chrome driver logs into the logs directory so let's check into the Chrome driver documentation put 3f here and for Chrome driver we want to have our output here somewhere else so let's check the services here's Chrome driver defined and we want to apply configurations on it so the output here should be logs and I want to actually run it with both so I see everything that's going on in the Chrome driver make this nice there we go I think we're good to go, let's give it a try running the same command you see the standard out is already much more as before, we see all the web driver commands as well as the Chrome DevTools command that the Chrome driver is sending to Chrome so let's see what we got we now have an allure results we have all the information from the test and to generate in the logs we have also the Chrome driver logs so that we the figure we saw in the standard out we also have it now here so we can exactly see when for instance the Chrome driver navigated to a specific page using the Chrome DevTools command page navigated in order to get the website for the Allure Reporter we should install, if we go back to the Allure Reporter docs we need to have the there we go the CLI tool so the CLI tool should be this we install it but without the minus G and to generate the website we can now call the Allure command check if it's there, there we go generate and what it wants to see is let's go back to the docs generate then the output here which is Allure results and say Allure Open let's see what it does generates the Allure results and serves the Allure HTML report in my browser so here we can now go through the suits, we have the before all hook the insert three items test and the mark second item is complete where we now see all the commands with their request and responses we also get screenshots if we want to the Allure documentation says where you can add custom things using the Allure Reporter you can also import it in your test to do specific things and enhance your reporting to it let's move on to the next chapter again I've not fully created all the steps here if you don't want to say npx Allure generate if you want to have this as part of your test run you can integrate this command here into an hook into an uncompleted so whenever the test run completes it automatically generates the HTML page for you and you can serve it from your AWS S3 bucket or wherever you want to store the Allure results let's move forward to the next chapter chapter 5 now we want to build a custom reporter and custom services and for that I recommend to look into the documentation for the custom commands and custom reporter in there you will see how these have to look like and I will just create a sample custom reporter that helps me to understand the commands that have been executed so I move away a little bit from the hands on workshop and just show you how to integrate a basic a basic custom reporter let me remove Allure again because I don't need to have that anymore and the service and Chrome drivers, there we go this can save so I recommend if you want to build your custom reporters for your projects to report any information from the test to anywhere else literally then a custom reporter is always good so let's say we create such custom reporter this custom reporter needs to be a class as you see in the documentation this example uses the import statement which is only available with the latest node and it's available so to run without Babel which I don't have set up right now I have to say module exports equals class custom reporter you can name your reporter anywhere you want what's important here is that you extend from the WDO base reporter this is important because this base reporter ensures that you can listen to all the information that you essentially want to listen to so you import that base reporter like this it should be already installed if you have a WDO reporter somewhere in your dependencies and then you can extend from it and this gives you the ability to just listen immediately on these events and the way our reporter works is that they you can define various of reporter functions let's say on before command which will help you to understand the command that is about to be executed and let's say how long every command let's print out the command that is being executed so in order to find out what parameters are accepted are expected here because that seems to be not documented we just go into the project and we just search for it and I make myself a note that this should be better documented we see the command here if you use TypeScript you would have already gotten this type support so I would not have to check but in this case the command contains a method and endpoint body and a CID so I'm just interested for the method which I'm interested in the body of the web driver command so to see what's being sent over that is being sent over to the web driver protocol to the driver unfortunately it's weird that I don't get the command name itself but it's certainly that is not working here so let's then just print out the body and integrate it to the spec so I just got a message in the chat can you use webdero services in standalone mode that's unfortunately not possible because the test runner has all the logic to connect the reporters to these events it's not possible for webdero if you use it in standalone mode so if you write tests with reporters and services always use the WS standalone never use a framework and build your web driver IO code around it because usually the webdero test takes a lot of things off from your shoulders so like for instance initiating the session we're doing reports for specific session IDs so for specific browsers that run a specific spec file which is really difficult to do if you use just marker to run your tests so here we can either not publish or package to npm to provide this package to provide the product to the community as we say custom reporter equals require and we require our custom reporter and then all we need to do is to add it to the reporter list and that should be it so now it should print all the payload that is being sent to the Chrome driver as a report so let's do this calling npxw again it's not a constructor okay so this usually means that I have integrated this in a one way let me see the docs okay let me see what I get back custom reporter exported module exports should be okay now this is a good thing about live coding and usually never works out so this should be the class there we go custom reporter let's just for the sake of it this should be actually enough I don't have any options it should find that we can also just try something else in a second let's just see what the custom reporter is maybe I have exported incorrectly so let's see class extends okay yeah I know what so the wi reporter is exported as a default so if I use require I need to set require a wi reporter dot default so can we move this and this about it now let's try it out okay we have a lot of locks there that are not good so let's say we say here it's silent and we say the output here is it defined here we have an output here for Chrome driver but not for web drive IO so let's set this your name so output saying putting setting output to the current directory will create wda locks instead of class or you know clustering your CLI your terminal so now it's all a bit cleaner and we see all the payload that happened from the reporter and you see it's just a console a lock if we now want to connect this information to the reporter then we can modify and say this dot write instead of instead of console a lock this will connect the information to the report output instead of just printing it out to the terminal so if you want to have if you want to put all your locks into a file you can do this by using the white command so the main reporter knows how to deal with this information so now we have now we have a spec reporter let's see and there was no config file created oh yeah we have one config file here the wdo00 custom reporter what a great name and we see all these objects here I can make this a little bit nicer by saying which this now it's better format so with this it is now better format and we see all the payload that we use for every command to open a url to find we use actually this selector how we entered the to-do and how we clicked on the toggle and so on you can do so much more with the reporter and building up your information and I would always recommend to extract all this information or extract all the reporters all the reporter code away from the wdo config file so you can just integrate your custom reporter logic into a separated file and just integrate it by adding this to your reporters list given that we have 20 minutes or even less than 20 minutes away from the end of the session can we move on to the next chapter let's see where we are can this remove all this let's move to chapter 6 again if you're stuck with this chapter you always find the solution in the solution directory with all the results better than I have them done right now but let's move to chapter 6 the source asset education so in this chapter we want to run our test we want to run it locally on a cloud vendor without doing much work so for that we want to add the source service to integrate better and add more capabilities to create a broader test coverage and as a bonus we want to run the test in the data center instead of the US so for that I create a new config file for this presentation it's important that you split up the config file based on the environments that you want to run your testing for local testing all I need is a Chrome browser to see if my application works but in order to guarantee the test coverage on all the other browsers I want to run this on source labs and for that I create a custom configuration file here I require our current configuration file which is WIO Conf and then export.config export a new config file that is based on the existing config file but I add new things to it one of the things is well I modify the services so now I don't want to use Chrome browser anymore I want to use the source service let's install that package real quick so NPME install at WIO source service we have services for other vendors like browser stack apply tools as well as testing check and cross browser testing I think so here you have the list of all services the lambda test service the thing is also cloud vendor testing bot and cross browser testing alright so we have the source service installed and now what we need to do is more capabilities we overwrite that property and say capabilities we now want to run on Chrome continue on the Chrome its platform version no platform name is windows 10 and the browser version is latest and I want to have the same for Firefox Microsoft Edge and Safari on Mac OS 10.30 okay do I need to overwrite anything else let me see I think I will just need the spec reporter for this use case so can we move this one and that's it the other properties and configurations stay the same and if you work like this where you have a base config it would make sense to also copy out the properties that you only want to use for local testing into a local.conf.js so for now we have this source config and it would run the same test we have the service integrated and we're good to go so let me run this and instead of calling the default config file we now use the source config file there's an export yeah this is not right should be module exports no exports or config let me see exports.config same as here okay this okay this needs to be done so in the config file we export the config property so we also have to use a named import to get through this information and there we go we get an error which is expected because a user key was not provided which is important if we want to use source apps so what we need to do is provide our username which we get which always should be received from the environment so in this case it's process environment source username and process environment source access key which I have in my environment already you can see here if you don't have it just export it say source username and then write something but I already have it there so this looks good have the access key and username provided and can try one this again so it's at the same time four browser sessions are being started let's see if the app works in all browsers the same way so they all run in parallel right now Chrome passes Microsoft Edge passes let's wait for Firefox I honestly doubt that they will pass but we will see it takes longer which is longer which is not a good sign we see now more log files here because we have now four workers so we see a zero worker, worker one, two and three and for worker one we can already see that the Firefox session is not being created for some reason Windows 10 and for the second we have also issues starting Safari on this machine on macOS maybe the environment is wrong so let's look into the platform configurator and get the right capabilities it's not always easy to get them right so that's why we have this configurator and let's see so we want to use WebDriver on a PC for Firefox on Windows 10 let's see Firefox latest and use a node code so we need to have browser version and Windows 10 so Firefox should look good and if we want to use Safari on Mac Catalina 1015 Safari latest I see a fingertip problem now it's looking good I think this had to be like this and we can write this small so in order to the file set is currently still in transition between the JSON wire protocol and the WebDriver protocol and to ensure that we use the WebDriver protocol at all times let's apply the source option which is the WebDriver capability extension and this will tell source hey use the WebDriver protocol please so let's see let's try this again I hope this will now work out and leave it as is so Firefox is starting Chrome is already running and we have also Safari running which is good let's strip back with one failure which is here in the test just for Safari we can now have a look into the job and see why this has been failed thanks to the spec report automatically it detects if you run your test on source labs and if you do so then it will print the job right there so now we can check what happened actually and apparently there was no click happening but something wrong with Safari could be either that Safari driver did not probably click on it or the application apparently does not work with Safari which I know but here we can check and see what's going on where the browser is located and we have all the locks in our hands another nice thing is with WebDriver you can just switch the location of the data center by saying I want to use the region the EU region let's remove two of the capabilities so by saying region EU you automatically now run the test on the EU data center we can also say to our service hey I want to run things on source connect I say source connect.true and I want to my tunnel identifier to be workshop so just by configuring this WebDriver and the service will do everything for you that needs to happen in order to download source connect now and to apply the tunnel identifier to the tunnel as well as to all your capabilities that you use so let's take a look at the chest but let's move on let's run these two capabilities and we can already see if we look into the locks now oh it has not started these are the old locks it just started source connect now it should be able to see that tunnel being opened so all the tests already have been closed down but in my locks I cannot see that the only manual is now the central one so automatically WebDriver will switch that on the manual for you to connect to the EU data center and just to show you that it was actually running over a tunnel I think she did not but I think it should be able to now should have been run over the source connect tunnel which is important when you want to test when your application is behind your network, your corporate network I think we're at the end of our time we have five minutes to go it's the last chance for you all to have a last question or just let me know how far you got if you just participated and what I've done that's awesome as well because you can always go back it's on github github.com you can always go there and run these chapters for yourself if you have questions don't hesitate to raise an issue or come to the WebDriver support channel that you can find at the bottom of our page right there where we as contributors can help you out and help you to understand what's going on in your test and when you apply WebDriver to your project we also can help you out if you see any errors and similar things last opportunity to ask questions on the workshop before we close the session or on the presentation thanks for sharing yeah I think the next chapters will be much more interesting where you go and move your application to use the to-do attitude the page object pattern so your tests look like this which looks much nicer than before and then you integrate visual regression testing and the last chapter will be about headless testing I see can we see parallel execution as we were already running this in parallel while we were running all tests on source apps just to give you an idea our main config is still to run locally and instead of one browser we define just two browsers just copy that and if we run this here we should see two browsers spinning up there we go WebDriver automatically runs test and parallel for you so you don't need to worry about that the network mock service I can go into that for the last two minutes currently it's not that easy to be honest to use networks modeling and stopping there is an example for that in the example directory so let's go into directory and go into examples DevTools and here you have an intercept actually no this is not using that we have an intercept service that you can use I think with the current one it's not really possible to mark network requests however there is a proposal in place to implement that and I'm super excited about this I will show you that for the second that allows you to network mocking go here it will allow you to mark network request with this new interface with the network interface where you can define a URL with a glob pattern and you then just tell how it should return or if it should be redirected to something we turn once this object and then with the next request should return something else it will be really flexible for you to mark network request and it will be supported in Chrome, Firefox, Nightly, Microsoft Edge as well as testing running things on source labs that will come up soon and there is more, just check out our issue list if you want to help us contribute find something in the world map or I would recommend to just filter the issues to first time us all and with that we are out of time and thank you so much for participating in the workshop and I see you online.