In this workshop, I cover not only what WebdriverIO can do, but also how you'll be using it day-to-day. I've built the exercises around real-world scenarios that demonstrate how you would actually set things up. It's not just "what to do," but specifically "how to get there." We'll cover the fundamentals of Automated UI testing so you can write maintainable, useful tests for your website and/or web app.
Automated Testing Using WebdriverIO
AI Generated Video Summary
This workshop focuses on testing web applications using WebDriverIO, with a demo website called Real World IO. It covers installation, configuration, and running tests using WebDriverIO. The Mocha syntax, debugging techniques, and timeout configuration are discussed. Selectors and their usage, as well as writing tests for the sign-in page and login functionality, are covered. The importance of stable selectors, custom waits, and variable declarations is emphasized.
1. Introduction to WebDriver IO Workshop
This workshop is based on the book 'The Web App Testing Guidebook' and focuses on testing web applications using WebDriver IO. We will be testing a demo website called Real World IO, which is a basic blog website. The main pages we will be testing are the sign-in and sign-up pages, and possibly the new article page. The code for the exercises is available for free on GitHub. We recommend going through the technical details chapter before diving into WebDriver IO. Make sure you have Node.js version 16 installed, and let us know if you encounter any issues with the commands on your machine.
Let's check out how today's presentation turned out. An Apple G隊 podcast with Kevin Lamping This presentation is brought to you by Ed Yellow and Stephen Green So hi, I'm... sorry about that. Kevin Lamping. I do front-end development and testing. I've specialized in web driver IO, the automated test framework for past many years. And so this is a workshop built on WebDriver IO and many of the lessons I've learned from using the tool for a little bit of time now.
Just a quick walk around the room. So we've got chats in Zoom itself, you can use that chat if you'd like. There is also the Discord channel that you can check out. And it is, you should have a link for it in your calendar invite, for the meeting invite, and there's specifically under TestJS Workshops, there is specifically a workshop for, or a channel for this workshop. I will paste that in the Zoom chat in case you need it. So if you have Discord, you can ask questions on there. It might be a little bit easier to talk back and forth. But otherwise you can use the meeting chat room as well in Zoom itself. Let's see. What else is worth mentioning? So also I've opened this up. It's not just a straight presentation, so you can verbally ask questions, just raise your hand through one of the reactions. And you can ask questions through there if you'd like. It's going to be kind of open, but I do have a pretty set of exercises I want to go through. So hopefully we'll be able to have a good pace to it. Let me know if the pace is going too fast, too slow. You can message me, message everyone in the chat. You can just message me. Specifically, I'll try and keep an eye on all of it. And then, yeah, we'll go from there.
So, organize things a little bit, give you, kind of. Share my screen, desktop, too. Okay, so this workshop is going to be based off of this book, The Web App Testing Guidebook, the first several chapters from it, we're going to hope to get through. And it's just about WebDriver I O and how you can test web applications. The application we're going to be testing today is the demo, demo website for this, real world app. And I'll show you real quick, Real World I O. There is this demo application that is written in a bunch of different implementations. We don't care about what those implementations are. The reason we're looking at this one is because I looked through a lot of different demo apps out there, like the basic to-do app. It's nice. It doesn't get you testing what you need to be testing. It doesn't have enough real world applications to it. So here's their demo. If you wanted to test on their demo, you could use their URL. But I actually have one that I set up specifically for our testing needs. So that's the real world app. That's what we'll be testing. It's just a basic kind of blog website. You can look at specific articles. You can follow certain things. You can favorite articles. What we'll be looking at testing today is the sign up… sign in and sign-up page. The… Trying to remember if we'll get to… Anything more advanced than that. I think we're going to test that we get… can log in. We might get into the new article. This is a little complex. But we might. It just depends. I don't know, we'll see. But yeah, testing this page as well. So I'll add a link to that in Discord and the Zoom chat. Oh, if I can find the Zoom chat. Where'd it go? There it is. So that's the link to that demo website. If you have Docker, I do have a Docker file that you can use to run your own server. Hopefully it works. I know some people have had issues with it recently. But we'll get to that in a minute. But if you have Docker and you want to try this out, you can get Docker started. I know that takes a few minutes to get Docker going. It can be a little slow. So yeah, that's the book. You don't have to have the book to go through the exercises. All the content in the book is actually available for free on GitHub. And let's send out a link to that as well. And I recommend that you go into this link because we're going to be going through these exercises one by one. And it would be helpful to have the code that you can directly look at as you're going through it. I did just make an update this morning. You can see updating it from an old style with WebDriver.io to a new style, like a newer version of WebDriver.io. So hopefully that all went through good, but there may be a bug or two because it's really difficult to check through hours and hours of content. But if you go to the manuscript, you can see all the chapters on there. We're probably going to skip through the first few chapters, but before we get into what WebDriver.io is, we can go through this technical details chapter. And in the book, it says Node.js version 14, I'll make a link to the Docker file, yeah. It says Node.js version 14. We should be able to use version 16 now because I have updated all the examples to async mode. We'll talk about what that is in a minute. But if you want to check what version of Node you have, you can open up a terminal, do node dash v, You can see I'm running 16.17. And this should work on Mac or Windows. There are some differences in the commands between Mac and Windows. So, let me know if one of the commands doesn't work on your machine. I'm running on a Mac so I'm going to type the Mac commands. If you're using something like git bash on Windows, it should work the same. But, yeah, every environment is different. And in my experience these workshops the biggest issue is keeping the environments happy.
2. Introduction to WebDriver IO
If you don't have Node installed, I would recommend a tool like NVM, Node Version Manager. WebDriverIO is a browser and mobile automation test framework that builds off of Selenium. It provides bindings for Selenium Server, Chrome DevTools, and other WebDriver-based browsers.
Yeah. If you don't have Node installed I would recommend a tool like NVM, Node Version Manager. And you can install Node through there or you can use the Node.js default installer. I'm going to assume most of you all have Node installed considering this is a TestJS summit. That's there.
Okay. We will... So WebDriver I.O. recently released version 8. This book was written for version 7. Let me see. I was going to see if I could do a poll on which version you want to use. We could install either version. I don't think that version 8 has anything breaking. We can go to their blog. No, it's not in here. They did... oh, I wonder if they've even released 8 yet. Ooh, maybe they haven't released it. They have either just released it or they are about to release it. Let's see. No, they're still on version 7. OK, that's actually good news for us. I don't have to worry about that too much.
So, let's get into what WebDriver IO is. This is a browser and mobile automation test framework. So, it builds off of... if you're familiar with Selenium, Selenium is a test framework and I actually have this in the book. If you want to read through in the book, we go through... in browsers and driving them... we talk about what all the different phrases are, all the different terms. So, there's the Selenium Project, which is the organization that provides tools for automated testing. And then there's Selenium itself, sometimes mixed with Selenium WebDriver, these are code programming language specific bindings for the WebDriver spec. The WebDriver spec is similar to like HTML5 spec or ECMAScript spec. It's just a specification for how browsers can implement automation so that tools, frameworks, like WebDriver IOU or Puppeteer can use that implementation for automation themselves. So that's WebDriver. Not to be confused with a browser driver. Browser driver is that specific implementation of the WebDriver spec. So ChromeDriver for Chrome, GeckoDriver for Firefox. Not sure which one Edge has. Edge, I think they're based off of WebKit. So it might be something in there. So that's a browser driver. You also have Selenium Servers. Now, these are servers that basically allow you to run multiple browser drivers. And all you have to do is point to a single server, and it manages loading, running, and sending commands to all the different browser drivers. That's really useful if you're going to test your application on multiple browsers. You're going to want something like a Selenium Server can help manage all those different browsers and sending all the commands to them. There's something else out there called the Chrome DevTools protocol. It's similar to Selenium WebDriver, but it's a bit different. It allows you to do more things like measuring timing, like page load timing, intercept network requests. That's something that Selenium slash web driver hasn't done a lot of, is intercept network request. But it is only for Chrome and Blink-based browsers. I always struggle when I say that. Such a tongue twister. Puppeteer uses the DevTools protocol to run Chrome. A lot of people, in my experience, they, just to clarify what Puppeteer is, in my experience, they think that Puppeteer is a test framework. It's not really a test framework. It's really an automation framework. And there's a difference with that. A test framework is specifically for testing websites. Puppeteer isn't specifically made for testing websites. You can use it for testing websites very much so. But actually you can use it for any sort of browser automation. So, say you want to do some scraping of a page, of a website every morning. That's not really testing the page. You're just trying to get information off of it. Puppeteer can do that. You can use it to automate. Say I want to go to this website and I want to print a PDF of it and then I want to e-mail it to me or something like that. That's what Puppeteer would be really good for. Or filling out a form. I once used Puppeteer... There was this form for logging my bike rides into work and away from work. But it was really slow and I really didn't enjoy it. So, entering the information for it. But I got rewards for entering the information. So, I wanted to get the information. So, I think I wrote either a Puppeteer script or maybe it was, maybe this was a like Nightwatch or if you're familiar with... About ten years ago there was a JavaScript testing tool called Nightwatch. Pretty sure. No, it was like... Ah! Can't remember specifically. But, anyway, I had this automation that went to the website and it entered the current date, entered the miles because it was always the same miles that I would ride and then would hit submit. And it was so much nicer just to have it do that versus having to manually enter it. That's like the one thing of automation for my life that I've ever done. Everything else I just manually push through it. Finally we have WebDriverIO. That's test framework written in Node.js, provides bindings for Selenium Server, but also Chrome DevTools and then other WebDriver based browsers. So WebDriverIO is not just Selenium, you have support for Chrome DevTools.
3. Introduction to WebDriverIO and Installation
WebDriverIO supports tools like Appium for mobile testing. We'll focus on ChromeDriver and Selenium Standalone Service. WebDriverIO has been around for at least eight years and has gone through many updates. It provides services and extensions for easily extending its functionality. There are also reporters for test output. Custom services and reporters can be created. To get started with WebDriverIO, open a terminal, make a new directory, and install the CLI with npm. Standalone mode is not necessary.
You also have support for tools like Appium as well for mobile testing. We're not going to get into Appium today. That's an entirely different subject. It's just its own thing is trying to get Appium working. It's a very similar to what we'll be doing, but just the setup of getting everything running is a lot more work than we have time for.
So here are the drivers. The main one we're going to want is ChromeDriver. We'll actually get this installed ourselves. We don't have to go to this link to do it. It's EdgeDriver. That's what it is. Those are your different drivers. We can manually install ChromeDriver if we want, and then run it just by running ChromeDriver. I'm going to skip past that because we don't need to do that. WebDriver I o is going to manage doing this for us. So, I just want to mention as an option is that we can use ChromeDriver. Alternatively, we can use the Selenium standalone server. Again, that's a Node.js install. And again, we're not going to do this because WebDriver I o handles all this for us. Let me think if there's anything else that I want to touch on with WebDriver I o.
One of the great things about WebDriver I o, it's been around for at least eight years. Got to be at least eight years. Gone through version after version after version. It looks completely different than it did when I started on version three. Yeah, it's gone through a lot. One of the big updates to it, I believe was in version four or five. They added services. So they used to have something like this but it wasn't really official. And so they had a couple of services like the, I think they had a Selenium Standalone Service, but it wasn't really a service, it was its own package and it wasn't, it was really kind of funky to work with. So what they did is they created services for easily extending WebDriver I.O. So as you can see here, we've got a lot of services available for our use. The main ones that we want to look at are the Selenium Standalone Service. So this will install Selenium Standalone for you and manage running it and everything. So even though it's just like an extension, we don't need to do this for actually when we walk through WebDriver I.O, which we'll do in just a minute through the intro of getting installed. It will install all of this for us. There's also the Chrome Driver Service. Oh, why did it go there? Oh, there it is. This is one you'll probably end up using today. And yeah, so these are just extensions that allow WebDriver I.O. to be more functional for what you need without really bogging down the core framework. So if you don't need the electron service, most people won't. You don't have to install it. But if you need it, it's there for you to use and pretty nice. They also have reporters. It's kind of the same idea, but this is just for reporting output of tests. The main one I use is a Lura reporter. So this allows you to see your tests, the report of how your tests ran, whether they failed, passed, were pending, things like that. It's pretty nice. There's still some work being done on it. It's all open source. So there's. I've run into a few bugs with it in the past, but overall it's a really nice thing to have. You can... Let me see. I know somewhere in here they talk about customer, custom services and custom reporters. There it is. We're not gonna get into this today, but I did want to mention with WebDriver I.O. you can create your own custom reporter if you want, or if you want, you can create your own custom service. You can use one of these different view focuses in there and you can hook into different parts of the test run cycle. So really nice, but I don't want to get into that too much. Okay, let's go ahead and get started with WebDriver I.O. You want a terminal open. You want to make sure you have node installed and we'll go out a directory. I'm going to increase the size of that for you. And we'll just make a new directory. I'll call it WDIO, just do test because. To test JS. This will be a quick one off directory. Oops. Test JS. I'll just show you how to get a basic project installed and then we can rerun through these steps for our specific workshop needs. So what we'll do is we'll do an npm install, npmi, at WDIO slash CLI. In the book, I don't paste that in both of them. Don't do that. We actually go through standalone mode first in the book and there's also a companion course to this book while this is running. I'll show you that companion course. It's basically the book itself just in video format and right now I've got about a little over half of the book converted to this. I don't know when I'm going to get to these. I've got a baby due in the next week or two so that's, baby's gonna be taking up a lot of my time. So it's going to be hard to focus on this, I think. Maybe I'll need an escape. But this, this course is out there and I'll send a link to it with a discount code if you're interested in purchasing the course. That's going to cover a lot of what we cover. Just in, with a lot less ums and uhs and pauses. I cut out all of that because that's boring to listen to and you don't need to listen to it if I can get it trimmed out. Okay, that's installed. The point I was trying to make is, I go through standalone mode but we don't need to go through standalone mode. It's not necessary. Okay, so we've got the command-line interface installed. That's the CLI.
4. Running WebDriver IO with Configuration
To run npxwdio, we need a configuration file. We can create it using 'npm init -y'. NPX is an NPM command that allows for easier command execution. We want the tests to run on our local machine and choose Mocha as the framework. For basic tests, TypeScript is not recommended. We'll use the default test location and auto-generate test files. The spec reporter is lightweight and sufficient. We'll skip additional plugins and choose ChromeDriverService. Selenium Standalone and ChromeDriver should not be used together. The base URL is not important for these tests.
With that, we can run npxwdio. And what this is going to do is it's going to look for a configuration file in our directory. Well, we haven't created a configuration file yet. And you know what I forgot to do? Hold on. Okay, it created the package JSON. Normally what I would say is to do an NPM init dash y. That will create your package JSON file for you. I forgot to mention that but it looks like it created it. Let's see what's in there. Yeah, just the dependency. Okay, that's good. It used to not do that. It used to just not create the file and it would be kind of annoying. Kind of annoying we don't have that dependency. But since this is just a one off, this is fine. So let's keep moving forward.
Okay, so I'll go back. NPX WDAO. If you're not familiar with the NPX keyword or command, that is an NPM command that was added in... Let's see what version we're on. I think it was added in version 7, so we're on 8. I think that was added in 6 or 7, so you should have it. And it allows you to more easily run commands. So what happens, we have our node modules folder that's endless. It's installed one thing and look how much is in there. Inside of there is at WDAO, actually, no it's bin ls, node modules, dot bin. You can see here's WDAO. And now, we're in the node modules folder. WDAO. This is the executable we want to run. So you could do dot slash node modules dot bin slash WDAO. You could do that, but it's just easier to type the npx WDAO. So that's what we do. And again, back to where we were. It says we haven't created or we don't have a configuration file. Would we like to create one? Yes, because we would like a configuration file. Great. So it goes through a helper, a wizard, and you can choose different things. What we're going to choose right now is we want these to run on our local machine. The automation backend is not where your browsers are running. It's actually, I'm wrong about that. It is where the browsers are running, because it's talking about Sauce Labs and BrowserStack. We're going to have our browsers running on our local machine. If you were using a tool like Sauce Labs, I don't think we're really going to get into these tools today. We'll see. Then you would want to choose that one, and it will prompt you for your username and your key. But we'll just do our local machine. Which framework do we want to use? I like Mocha. I've used Mocha for years. A lot of people like Cucumber. Some people like Jasmine. We're going to stick with Mocha. It's a lot easier. I don't have to go into detail about what Cucumber is and how to get all that set up. So we'll just stick with Mocha.
Compiler, you can use TypeScript. For testing, if you're just writing basic tests and you're working on your own on these tests, unless you are familiar with TypeScript, I don't recommend using TypeScript. It's not necessary. If you are working on a larger team and you want to enforce some better practices, TypeScript is worth it. It does help. Like if you use it correctly, it can be very useful for ensuring better documentation, better self-documenting code, that sort of thing. So there's nothing against TypeScript, but if we're just writing basic tests, I don't really recommend it. It's more work than it needs to be. Yeah. Where are tests located? We'll just go with the default here. We'll look at that folder in a minute. Do we want to auto-generate some tests files? Yes, we do. We're not going to use page objects for now because that's a little bit outside the scope of what we want to get to, so we're going to say no to the page objects. Now we have options for reporters. You can choose multiple if you want. We're just going to go with spec. That's a good little reporter. Lightweight, but does its job. So we'll choose spec. We're not going to use any extra plugins, so I'll just hit enter. And here, we can add services. You see ChromeDriverService is already set up. We could also go down and use Selenium Standalone if we wanted. Make sure if you want to use Selenium Standalone, you do have to have Java installed. That's a requirement. I'm going to skip choosing Selenium Standalone for now. Don't do both ChromeDriver and Selenium Standalone. Choose one or the other. Because they do the same thing. And so if you have both installed, they're going to fight with each other, and you don't want them fighting. But yeah, that whole list of services is on the WebDriver.io website. Now we have, what is our base URL? We can just hit Enter for this. We'll talk about base URLs in a little bit. It doesn't really matter for these tests. They're going to kind of ignore that value.
5. Running WebDriver IO Tests
We can run our tests using the command NPXWDIO. The test goes to a website, enters some information, and checks some things. The outcome of the test is displayed along with logs, which are useful for debugging. If you encounter any issues, you can delete the folder and try again. The book provides answers and information on configuring WebDriver IO. The command npxwdio --"help" provides information on available commands.
So we'll just hit Enter. And then, yes, we want it to run an NPM install and install our dependencies.
Okay, now everything has been installed. We could run our tests. We actually don't need the full command. We can just run NPXWDIO. Let's do that. So we're basically running the same command that we already had. This time it sees the configuration file, and so it's not going to ask us to create one. It's just going to run our test. So you see, by default it's running, but it's got a different name. We can also run this test with the default code. This is going to run our test. So you see my... Real quick, I'll do that one more time. I think I will. So it goes to... goes to a website, enters some information, checks some things. Here is the spec reporter that we just looked at, and this is the outcome of our test. So along with that, we have a bunch of logs. These logs are very useful for debugging for when you run into an issue where the website isn't... or the test isn't doing what you wanted it to do. It'll give you some important information about what's going on. We'll go to those logs in just a minute, but for now, I want to open up... my... the... tests and everything in this package that we just... went.
Before we get into this, does anybody have any questions? Did anybody run into any issues with running this test? I'll give you all a minute or two.
Sorry, can you go a little bit upper where you configure WDIO configuration helper. I missed this part, just... Yeah, that part, just 30 seconds. I will... Please. OK. Bruno, you missed a file. What? What error? What are you running into? Interesting. These examples come through, do you want WebDriverIO to auto-generate some test files? You might have needed to enter a capital Y on that. I don't know how case-sensitive it is when it's going through there. It installs fast enough that you could... What you can do is delete this file and then run the command again. That's one option. Let me see, I think... Yeah. There, I'll paste that in there. OK. Yeah, so if you mess something up, you can just delete... You can delete the whole folder. I mean, we're early enough, you can just delete the folder and try again. And if you're looking for where in the book to... This is at. This is under upgrading to the WebDriver IOHTestRunner. And all the answers are through here, stepping through the configuration utility. I was wondering about something, hold on just a second. I can do that. Let me see. I don't think I can. Never mind. I was going to look at sharing a print copy of the book, but it's not going to be easy to do. Unfortunately. But yeah, all the answers and stuff are in there for what we go through. That was the other thing I was going to say. You can do npxwdio --"help". It'll give you information about the commands you can run. Well, one thing that it tells you, here to run your test you can run this full command. You don't need to include wdio.conf.js. It automatically looks there for you. This is only if this is in a custom file location, like if you have a different name for it, or if you have it in a folder. You also don't need to include run. It'll use run by default so that's why we were able to do npxwdio because both of these are defaults. If we go back down here, we have a couple of other options. We can do npxwdio.config. That will go through the initialization again, if you'd like. If you need to install any services, there's an install command. There's this cool REPL. I don't think we're going to get to it but I might show it off in a little bit. But this allows you to run WebDriver I.O. commands in real-time basically. Instead of running it through a test script, you just type it into your terminal. It's really nice. Really good for debugging when you need it. And then there's the run command, which is the default command for running your tests. They have some examples here of some more custom stuff so you can do suites. If you want to run a specific set of tests or a specific test itself, that's also available. You can do –spec. We will end up using this argument because it's very helpful when you're debugging tests to be able to run just one test. Run a scenario. You could actually pass in a specific line number for running. These are neat. This might be specific to Cucumber, though.
6. Mocha Syntax and Function Usage in WebDriverIO
The Mocha syntax uses describe and it for organizing tests. Multiple it statements can be added to describe, and multiple describes can be nested. The fat arrow syntax for functions may cause issues with timeouts in Mocha. Using the function keyword instead of the fat arrow syntax can resolve this. Both function and fat arrow syntax can be used. In Mocha, async and await are used with functions that require them. The async and await syntax is not required in older versions of WebDriverIO.
Great, it is passing now. This is kind of what it looks like for installing. That's available npxwdio –help. Hopefully you all can see the bottom of my screen. Really good info inaudible just in case. Let's go into this folder and see what was created. First we have our test. If you are familiar with unit testing. Let's increase the size of this. That's good. If you are familiar with unit testing, you might have used a tool like Jest or Mocha or Jasmine. This is Mocha syntax so it uses describe and it. This is just for organizing your test. This allows us to organize our test into specific features. Here we want to test that it allows you to log in. All of our test code for that gets added to the it statement. It's basically a function that you are calling. That gets added to describe. We can actually have multiple it statements. Say we wanted to test invalid credentials, or test something else. You can have multiple it statements inside of a describe. You can also have multiple describes with it statements in there. And we'll talk about the format of this in just a minute.
One thing I don't like about this auto-generated code is that it uses the fat arrow syntax for functions. One thing that you're able to do in Mocha is, say something about this test runs a little bit longer. You can set this dot timeOut. Say you want it to run a lot longer before it fails. You can set it this way, but if you use this syntax, this isn't going to work. This is going to fail because this is not referencing what mocha thinks it should reference. It's this really really crazy use case that I'm actually regretting mentioning, but it's like, this will drive you insane if you're reading the mocha documentation and it tells you to do this thing and it's still not working. You have to figure out what you have to do instead is use a normal function, then this command now works. So for me, there's no benefit specifically to writing it in this style, aside from it's a few extra characters. Question of why not use global timeout? I don't know if global timeout works with Mocha, but I think one of the issues with global timeouts is that that updates the timeout for every test and the same thing with updating the timeout in your configuration. It does that for every test. What we want to do is just this one test, there's something like maybe the server is a little bit slow for this specific action or this is just an action that takes extra time, like it's uploading a document and it's a big document, so it's just going to take five extra seconds and that normally will reach the Mocha timeout. So you'd want to do something like that. Okay. There's another option of putting a timeout at the bottom. I don't know if this works in Mocha. I'll take your word for it. I think my biggest pet peeve though, is if we go through... Let me bring it up. Yeah. If you look through the documentation, it specifically says this.Timeout. But, yeah, if you look through the documentation, it uses this.Timeout. But, yeah, if you look through the documentation, it uses this.Timeout. But you notice it uses the function keyword, whereas we're not using it. So it's just one of those things where it's just not that beneficial to use the syntax. And it will just create a situation — it's just one of those bugs that you're going to bang your head against the keyboard for an hour thinking you've lost your mind. And it turns out that you just need to use function instead of that. So just be aware of that. I don't want you all to run into that issue later on in life. So hopefully you'll remember. Okay. Either one works, whether you want to use function or whether you want to use the fat arrow. I don't know which one I'm going to use, actually. I'm going to try and use function, but we'll see. So back to Mocha, yeah, you can have multiple describes inside of each other. You can have multiple its inside of a describe, that sort of thing. You can organize it pretty well. And this will actually come across, we'll go to name of the discord channel, sure. There's a link to it. It's under Git Nation and then under TestJS Summit, they have TestJS workshops. Responses. Yeah there should be TestJS workshops. Did they not open it up? Message reply. Okay let's see if they can get that fixed. In the mean time, real quick show, this describe and this it block get sent to the reporter. If we go back to our report. You see there's the name of our describe, there's the name of our it block. So that's the basics of how Mocha is set up. This string can be anything you want it to be. It's just text and it's only for your use. Same thing goes with the it string. I like the syntax of it should. You don't have to do it. I've seen many times people just do, they just name the test instead of it should. It's up to you. It's whatever you prefer. That doesn't really matter. A thing to note is in the describe, we don't use this async keyword. It doesn't really need it. But we do need it for our functions because we're using await. And this async and await, we didn't used to have to do this in WebDriver I.O.. So if you're ever looking at tutorials and you just see it like this, that's an older one. And I'm a shit fan too. I really like it. I think it should, it just reads so nicely in the code. Okay. I get distracted.
7. WebDriver IO Test Execution and Configuration
If you're ever looking at older code and it doesn't have awaits, it's just because it used to support not having to use async and await. But there was a change in Node.js version 16 that dropped support for a framework that a web driver. In order to support later versions of node 16, there was a shift to just start using a sink in a way. Mocha is a sink await and will wait for the next it. In all of your test files, you have access to a global browser object. The first thing we do is go to the URL using the URL command. We then get the element with the ID of username and set its value to 'Tom Smith'. We do the same thing with the password and click the login button. We use assertions to check that the flash element exists and has the correct text. WebDriver.io retries checking the element until it is found or the timeout is reached. The expect library provides useful matchers for assertions. The configuration file defines the spec files to run, the browsers to use, and other settings.
So yeah, if you're ever looking at older code and it doesn't have awaits, it's just because it used to support not having to use async and await. But there was a change in Node.js version 16 that dropped support for a framework that a web driver. I always using to allow you to skip using a sink and await and um, in order to support later versions of node 16, there was a shift to just start using a sink in a way. It's bulkier like it's extra typing and you have to know when to use it specifically with your expects. There are some times you don't need to use await. Say I just want to create a If I want to do like URL equals Say I want to do that like I don't need to do an await here But anytime you're running a WebDriver IO command Like browser or dollar sign we'll go into these commands in just a minute You do need to use a weight and so you'll you'll see examples of what that looks like Mocha is a sink await and will wait for the next it. Yeah, so Mocha's smart enough to know that this function is Asynchronous, and it will wait for all your awaits to go through before moving on to the next it statement So let's look at what this code does so the first thing we do In all of your test files you have access to a global browser Object if we go to the web driver. I a website we can go to the API you see here's browser and On browser we have a lot of commands we can run the one we specifically use here is URL Pretty basic it takes you to the URL you provide There's a couple things so you can go directly to the URL or You can use a relative path That's using that base URL that I was mentioning We'll get to that in a little bit, but for now we just use the direct URL So this will just load that site Wait browser URL This will wait for the browser to go To that URL and then run the next command The next command is going to be we want to get an element with an ID of username So if there are any jQuery fans here from the late 2000s there was a $ command that allowed you to select elements on a page We can actually use this right now. So let's ourselves Go to this website and I'll open up my just inspect Now I'm on the console and I believe Let's see, is that going to work? Yeah, it worked Maybe because they have jQuery on the page so I don't know if that actually always works or not Can't remember. Let me see, I don't think they would have jQuery. Oh, they do have jQuery on the page but basically what this says let's It says I want to reference this element this element being the username input and the reason I want to reference that is I want to enter text into it. That's what my test is for. So I want to enter Tom Smith in here So go back to our test. Let's see if I can do this Get it through here We're gonna get the element and then we're gonna set the value on that element So if you're familiar with CSS selectors, I kind of assume most people here are familiar with CSS selectors This is just a CSS selector We'll get into selectors in just a little bit I don't want to go down that rabbit hole yet, but all this is saying is get the element that has an ID of username Once we get that element I want to run Set value and I'm gonna set the value to Tom Smith So set value There are our browser commands and you can see our dollar sign command is in here But we actually you could do browser dollar sign but web driver I Oh makes dollar sign Makes dollar sign available as a global in the same way. It makes browser available as a global So you don't have to do browser dot dollar sign that saves you a few keystrokes So if we close browser there's the element one and Element is essentially what gets what gets returned from the dollar sign command So we'll come down and we see Yep, good old J. Query The set value command that we're using in our code Here is Tom Smith and What we do is we pass in the value Surprise, it's just a string or a number it can actually be an array of strings If you want to do something very specific but for our needs, it's just a basic string and It sends Tom Smith into our username field And then we'll do essentially the same thing with the password Call set value again and Run it then we get another element this one. It's a button. It has an attribute of type that equals submit You know guess what that is not the lot. It is it's the login button Let's see. So we have a button here as a type of submit so that's what that selector is getting and then we're gonna click it I Don't think I need to explain what the click action does Clicks the button, okay Thankfully, that's I feel like that's pretty self-explanatory is the click action just does a mouse click on the button so that's gonna enter your User name your password and then it'll click login Oops, let's try this again. I had an extra space in my password Now we're into the secure area this internet app If you're not familiar with it, it's got just a bunch of examples in it. It's pretty good for Writing one-off test and showing things off like an example test for a test framework test framework Does browser support Dom API? We'll get to that in just a minute. I'll talk about what kind of selectors you can use it everything You can select multiple elements. We'll get to that in a minute, too The last thing we want to do so we've gone to our login page. We've entered values. We've clicked the button How do we ensure that our test actually passed because that's a whole point of writing this test is making sure that it actually passed Well, we do that with assertions And here we're going to assert that there's an element that has an idea flash And we're expecting it to exist Or to be existing We're also going to expect that element See Yeah has this specific test text you're logged into the secure area So this is the element. We're checking Look at that element. We have an idea flash so it exists on the page and It has the text you're logged into a secure area and you see it says text containing If we got rid of that and just had to have text Let's see what that does see if it fails Okay, so you see it's trying this command again and again and again It's trying to find the element or if it found the flash element It's waiting for it to have this text in it The reason it doesn't have this text in it is if we go back to our browser you see this little space before This little extra white space causes It not to equal this text so this should be something like a space here, I don't know if it needs spaces after I'm going to do a space here after 2 half text is very specific. It has to be white space and all. Correct, so that's why we use 2 half text containing 2 half text containing just checks that that element has this text in it somewhere So it doesn't care about the white space around the end That's the difference between the two But one of the really nice things about what WebDriver.io did for us was it waited for or it retried checking that element. That's incredibly helpful because web apps don't always have like they're Somewhat asynchronous in that you'll take an action. It won't reload the browser immediately But it also won't Make that whatever action you took won't happen immediately It might take half a second. So with these retry commands it will keep trying until Either it reaches the timeout, which is what happened here, or that element is found and That's really useful for Testing hopefully we'll get to that in our examples later on So those are two assertions This expect library you don't have to install it it comes with WebDriver IO. It's already there We'll be getting into a bunch of these assertions in a little bit, but if you are curious You can look at the expect library here We can check that the URL is correct. We can check that the page title is correct We can have our element matchers to be existing just checks that an element is on the page You can check that maybe an input has a specific value like if you have some sort of auto formatting on your inputs You can enter Enter your you can set your value and then Check the value gets formatted to whatever Yep all sorts of good matchers in here. It's also based off of the expect JS Library assertion All of these matches are also available which is pretty useful here and Awesome we're in discord. I'll keep sending it to both chats just in case you're not in discord Okay, that's the test itself does anybody have questions on this test All you need is a basic overview of kind of what things happened We'll get into specific commands and more detail on all of that in a few minutes Yeah expect is really useful They didn't used to have this Expect a search in library built-in. You used to have to do chai and You'd have to do stuff like if you wanted to check this you'd have to get the text and Then you'd have to do like to equal Something like that and you'd also have to like trim the text because there was no like containing and then you're if this failed It wouldn't Yeah, it wasn't it wasn't a nice failure. It wasn't a helpful failure most of the time Whereas here in in our test failure You can see it expected our element to have text of this Expected zero received one Yeah So Yeah, this expect library is really helpful that's all I'll say let's go and do all of this Okay the next thing I want to do is let's look at this configuration file that we have and then we'll take a break For 10-15 minutes on 10 15 minutes something like that So our configuration file this Is there an equivalent for electron? I'm not I don't understand the Question there like is there a way to test electron? maps Yeah, there's there's an electron service I saw it earlier I don't know how well it works I've only done a little bit of electron work Okay, so this is the configuration file this is all auto generated and it's got a lot of good documentation in it I'll go through I'm not going to go through every detail, but a few things to note is this is where we define what spec files we want to run. If you want to change that, it uses the glob pattern so this checks for any folder inside of spec or sub folder inside of the specs folder. I'll create a new file. Any file that ends in.js that will be run. You can also exclude files if you'd like. This max instances allows you to run multiple tests at the same time. It's based off of files so if you have 5 files and you have a max instances of 10, all of the files will run at the same time. This can really speed up your tests but it can also break your tests because all your tests are running at the same time. If some of the data conflicts between your tests, like one test changes the data that another test needs, you can get failures there because they're all running at the same time. You might want to set that to 1, I prefer having tests that can run at the same time. That's just something you have to consider. Your capabilities are where you define all your browsers. Here we have Chrome, which is our only browser that we're running. You can also override the max instances for this specific browser. We don't really need that. You can also say, I only want to run these specs. Whatever. If you only want to run a specific set of tests on this browser, you can do that. You can also exclude as well. You notice it's an array, so you can exclude multiple items if you'd like. Yeah. There's more to what this capabilities ends up looking like. That's all in, let me see. Docs, configuration. Capabilities. Let me see. I'm trying to see if there's anything else in the documentation around it. Not much documentation here about what you can enter into capabilities or not. Maybe here. Yeah, there's a couple more things in here I like the fact that you can set up some custom Google options. That's kind of nice for when you need to do downloads. You can also run in headless mode. In this example, at least, we have our Chrome browser with all its configurations and then Firefox as well with its configurations and you can see it has specs for running in just Firefox. So if we go back to here, we can create a second capability for running in multiple browsers. If you're using something like Sauce Labs, you're going to want to use this platform configuration tool. It's really nice. We can get into that, maybe, I don't want to spend too much time on that. Log level is the output of here, so our logs. You see it's all info right now. Sometimes you might want it to be a little bit more informative, so you can set that to Trace. Trace is the highest level. Silent is the lowest level, and so Trace will include anything from all the other logs. Debug will include anything from here in, Info will include any log from there in. I would go with either Trace or Info. Debug, I haven't really noticed much of. There's not a lot of debug stuff out there. It's mostly Info, but sometimes you might want Trace. If you're on CICD, you might want to just do WARN. I don't know, it's up to you. But that's where you can change that log level. You can also set it for certain services, but we're not going to get into that. BAIL is...
8. Configuration File and Hooks
If a single test fails, you stop running every other test. Here's that base URL that we talked about. Your default for timeouts. Services. Your framework, you should never really change this, and once it's set, it's set. There's a couple options in there. The configuration file ends with a bunch of hooks. And these hooks are useful for running code before or after your tests. So onWorkerStart, onWorkerEnd, beforeSession, before, beforeCommand. That's a configuration file.
If a single test fails, you stop running every other test. You don't worry about any other tests. As soon as one fails, stop running the others. That can be helpful for debugging.
Here's that base URL that we talked about. We're going to get into that later. That's that setting. Your default for timeouts. This is your wait for timeout. Any wait for commands or expectations. Expect such and such to have text. It's going to wait 10 seconds, so 10,000 milliseconds or 10 seconds. You could also change that if you want to be something like that. It'll work just the same. Don't worry about this ConnectionRetry stuff.
Services. So here we have our ChromeDriver service. You can add multiple services. Your Selenium standalone. But again, you don't really want to do that. You'll also notice some services get a little bit more complex in their configuration, so you add your configurations for your services here. I would, if you're going to install a service, use the command line to run the npxwdio install and then whatever service you want, and that will update this services line for you. I'm pretty sure. Yeah, so. Because it's kind of complicated how the configuration gets set up, so if you can have WebDriver.io take care of that for you, have it do that.
So your framework, you should never really change this, and once it's set, it's set. There's a couple options in there. You also have some more options here. So your timeout is set to 60 seconds right now. You can have this timeout depend on an environment variable you passed in. If you're familiar with environment variables in Node.js, you can do something like debug equals true. So what this is going to do... 1234567 This is going to say if the environment variable of debug equals true, then use a really long timeout. Otherwise, use 60 seconds. I don't want to get to that just yet, but it's so helpful, we might end up using it later on. So if you want to just paste that in there. I'll show you what this specifically looks like. But it's a nice little tip to have. I kind of wish that it was part of the default to have it in there because it's one of the first things I said. That's really helpful in the future. We'll get to that maybe.
The configuration file ends with a bunch of hooks. And these hooks are useful for running code before or after your tests. So onWorkerStart, onWorkerEnd, beforeSession, before, beforeCommand. I use before pretty often. Hopefully we'll get to take a look at what before looks like. But basically, before any test executes, you can run a hook. So here, it says, perfect place to define custom commands. You can do that if you want. We can just do a console.log capabilities. And say we run our tests again. Now way up here, you see this is saying, this is letting you know which hooks are running. Somewhere in here, like right here is where that hook would run. So if I saved it, let's just go ahead and do it. Why not? Oh, what did it not like? That's right. It must provide a pattern. Oh! Oops. Left in some example code. Okay, we don't care about that. What we care about is making sure that it didn't lied to you. Yeah, here's that capabilities. So, again, in my code, in this before hook, where are you? I logged out the capabilities, and then here in my console, you see those are the capabilities that got logged out. So we have our browser. This is the ChromeDriver end point. So ChromeDriver starts up a server on localhost at port 9515, so that's what that is. Finished running before hook. So you can kind of get some information in here. I guess that's a debug information right there. There you go. There is some debug information. And then there's also, excuse me, after hooks, as well. So if you want to do something with the tests and the results, this is where a lot of the reporters put their hooks in, these after hooks. I've used maybe two or three of these in my entire time working with WebDriver I, I don't use them that much, but they're really helpful for services. Really, really helpful for services, so just keep those in mind. And yeah, that's a configuration file. Any questions on that and then we'll go on break?
Okay, so it's right around my time, 1015, 1016. Let's regroup in 10 minutes, so whatever the hour is that you're at, 25, unless you're in one of those weird time zones where it's half an hour, so 10 minutes we'll be back, video's messed up, come on. There we go, I have multiple plugs on now because battery ran low and it won't connect to my other set of headphones. Let's see how long these last because there's also a nice buzzing in my ear because they're being charged as I'm using them. That's wonderful, I wonder if I even need them charged for how I'm using them, I think so. Yes, wires are so much fun. Okay, so we just finished up the configuration file and looking through the example code. It's not actually on, so I can still hear music, it just doesn't have the noise canceling but it doesn't have the buzz and that's the important part. I don't want that annoying buzz. Awesome, still hearing me great, yeah, that's because I've got the microphone so don't have the headset stuff going on. Did installation, now let's go ahead and take a look at writing some tests for this real world website. So we've got that basic example done, we're gonna go back to here and I'm going to go up a directory and you can just delete this if you want. That was just for demo purposes. We'll create a new one, make directory, we'll call it WDIO real world, come on, I don't actually want to autocomplete, what did I do wrong? There, and I'll do an MPM init this time. So MPM init-y, so this creates a package.json file for us.
9. Setting Up WDIO/CLI and Docker
The next step is to install WDIO/CLI and use the demo website. There might be an issue with conflicting data if multiple people run the same test that modifies the same data. To set up the Docker file, copy the contents of the docker-compose.yml file and paste them into a new file. Run 'docker-compose up' to start the Docker containers. The web server is a Vue.js app, and the back end is a NodeExpress real world example app. The front end uses Vue.js, but React can also be used. The demo apps may have bugs, which can be advantageous for testing purposes.
You see one thing it has is these scripts, so we might take advantage of these in the future. The next thing I'll do is our install of at WDIO slash CLI and let that run. Now we can use this demo website. There might be an issue, I don't think we'll get to it, but if we were to get to it, there could be an issue with conflicting data. So having multiple people run the same test that modifies the same data could be an issue. I don't think we're gonna get to it. So we should be fine just using this demo website. But I do wanna show getting set up with the Docker file and I'll paste that again there. So you'll just, if you have Docker running, which I do here, you can copy the contents of this or save it. Let me see. I'll just copy it over. This can be in any directory, any folder if you want. I will just, docker-compose.yml. Yeah, that's what I need. That's what I need and then I'll open up my code editor to this new one. Go into this docker-compose file, paste it in, and hopefully this will start. Show the commands on the new folder or was the same? Yeah, it was just a, making the folder, going into it, NPM init. That was the one new one. So this just created a package JSON file, which is essentially what the install will also do that, but the reason I like that is it comes with a few extra things in case you wanted to fill it out for whatever reason. So I'm gonna go in install for WDIOCLI. I created a docker compose file, touch just creates a new file. If you wanted to in like your code editor, just create a new file. Call it docker compose, paste in the contents from that gist I sent. Fingers crossed this works, docker compose up. Dash D-U-M-P. I think that's the command. Let's see how this works. Forgot that I had to download all of this. At least not too big. Let me look in the book, this is under a real world app. Here's that Docker Compose file, if you wanted to get there as well. Yeah, Docker Compose, that's what I ran, right? I did a dash D, which I talk about. There we go, scroll sideways. Dash D, that'll just run it in the background, so you don't have to open up a new tab if you want. Still downloading a few things, there's also a way to manually self install and run it. I am not covering that, so if you wanna try that out, go for it. Yeah, it's so particular to whatever machine you're on that I don't wanna bother with it. Hurry up and download, I should've done this before. Man, it keeps going, huh? So there's two parts of it, well I might as well mention what's going on with the server you've got your web server. So this is a Vue.js app. And let me see. Nope, not that. Ah. Something real world, forget what my URL is. There, ah. That's not the right one. Here. So this is the back end. And then... This is the front end. Here we go. That's the front end. That's the back end. You don't need to do anything with this. I'm just showing if there's anybody curious to know, kind of what's going on. This is forked from the NodeExpress real world example app. I did this not... More recent than three years ago, maybe. Yeah, there you go. Back in a year ago. Kind of worked on this, so. The hardest thing about these is keeping it up to date two and a half years later. But one of the things I did to update this was I added these element attributes, data QA ID, to some of these elements. But this is all just, the front end is all Vue.js. But you can use React if you want. The thing is the demo apps, while they're all supposed to be the same between the different programming languages, they're not. Some of them have bugs. This one had some bugs that I actually ended up taking advantage of for testing purposes. So yeah, that's that. Okay, now that's all done. You can see it says that it's done. It doesn't look like anything's happening, but if I go docker ps, you can see I've got these containers now that are up on port 8080. So if I go localhost 8080, there we go. Why does it say loading articles? This might be the issue people were running into. Try that again. Articles, there isn't a server error. Uh-oh. Okay, so you might, you'll probably run into this issue. Um. People reported it somewhere. Where did they report it? No. Not here either. Maybe in the book? Uh, maybe it was just in my email that I got it. Um, Okay, I don't really have time to debug this right now. I don't wanna waste your time with it. Unsupported OP client driver may require an update, so this is Mongo. Real quick. Let's take a quick look at what could be going on. Where'd it go? Where'd it go? Where'd it go? Where'd it go? Here. No, that's the book.
10. Mongo Database and Web Driver IO Configuration
We pulled the Mongo image version six and tried specifying version five. If you want to run it, you can use the localhost or the online demo. We have web driver IO installed in our new folder and ran npxwdio to create the configuration file. We chose not to auto generate test files and set the base URL to our demo URL. We created a new test file named navigation.js in the specs folder.
Oh, Mongo database six. What do we use? We just use, not Mongo seed. That's something else. Real world Mongo, image Mongo. Um... Docker...Mongo... This is where we pulled it down from. So you see version six. I bet we could get away with specifying version five and trying that. And I really wanna try that. Uh, tags. Sort, newest, focal, 6.2, 6.0, 6, there we go. I don't know what focal is so I will just take this tag. Copy that back over here. Do a Docker compose down.
Okay, now that stopped it. Now Docker, pop-d. This shouldn't take as long. It will re-pull the mongo image, but it shouldn't redo all the other ones. So, hopefully that gets rid of that. And, just for your needs I will show that in there. And also in Discord. Get back to Discord, there. If you want to run it. Hopefuly that works. If it doesn't work we'll just keep moving forward. How much more do you got? Okay, where is my course? That is available at learnwebdriver.io. I'll give you all a coupon for this. But... Yeah, if you want to read through all of the content in there, what's in there and all that, pricing and all that. What I'll give you a coupon for is sixty percent off this in action package. I'll have a link for that later. Well... I'll send it now, I'll send it later, whatever. Copy link address. Hopefully that works. But that comes with the book as well, if you want that. The book, the published book, is still using the old sync mode. Just so you know, I am mostly done. I've got to finish these two modules in the book. Basically the two chapters in the book. The modules and the chapters kind of line up with each other. So, I've got to update those two but it shouldn't be too much extra. I just haven't done it. Okay. Let's try this now. Fingers crossed. There we go. Okay, great. So that's what you have to do to get that working, is use that specific image. So, that's localhost if you want to use localhost. For our needs, I'm going to use the demo, the online demo, just in case people want to use that. But this is running in the background. You can always check that with Docker or PS. You can see that it's running and then you can always do Docker compose down to bring it down if you want.
So, we've got web driver IO installed, the command line in our new folder. I'm gonna run npxwdio again and this is going to walk us through the Wizard again. So we'll hit yes because we want to create that file again. We'll test locally, we'll use Mocha, no on our compiler. We'll keep the tests where they are. This is our first change. We don't want web driver IO to auto generate test files. We're going to create these ourselves. We will do the speck reporter. We won't use any plugins. We'll, just for the sake of it, I'm gonna choose Selenium standalone just to show you how that works. There's not much difference. You can stick with Chrome Driver if you want to use Chrome Driver. The examples are going to work pretty much the same. But I'll just say Selenium standalone if I want. There's that electron service. Then the base URL, I'm going to use our demo URL here. No slash at the end. I can't remember if slash matters or not, but I'll just keep it off. Then yeah, we want to install it. Okay, I'll open this up. Actually, I already have it open here. Here's our new file. If we go down to our base URL, you see the base URL is correct. It's correct. Now, we don't have our test files or our test folder because we told it not to. I can just create a new folder in here. I think it was test. Yeah, test. Then in there, I'll create a new folder specs. We'll create a new file and we'll call this navigation.js. This is going to be our new test file. You can do this in the command line if you want. Oops, no, geez. I did not mean to do that.
11. Writing Test, Debugging, and API Requests
In our test, we load the homepage and check the title of the page. We also discuss the use of base URLs and the difference between using dot slash and slash. Additionally, we explore the browser debug command, which allows us to pause tests and inspect the browser. We encounter issues with Java runtime and fallback to using Chrome driver. We run WebDriver IO and examine the API requests sent to the web driver server.
Into clear, you can do make-directory-p, at least in Mac, and then test-specs if you want to do it that way. But you don't have to. Did the exact most host matter? For the base URL, yeah. You're talking about HTTPS versus HTTP. Not sure which reference to the exact hosts we're looking at.
Okay. Cool. Y'all are asking easy questions today and I really appreciate it. Okay, let's get started with writing our test. So what we wanna do in our test is very basic. We just wanna load the homepage, and we wanna check the title of the page is Conduit. And let me see what else. Oops, manuscript. We are trying to get the host title of the page. We are on site loading and navigation. Double check. Talks about some issues we ran into. You see here we install a specific version of WebDriverIO. That's an option if you want to. We should be able, the latest is 7.25. So we don't really need to do that. There's running our config with our configuration helper. You see this is what that looked like for our base URL. It did include a slash in there. I can't remember if the slash matters or not. Create a new one. I didn't talk about it here, what we're actually testing. Let me cheat just a second. Okay, so we're going to get the URL, get the title, click the sign in button, then get the URL. So, we're gonna come here. Get the title of the page. Click sign in. And then we're gonna check the URL that it's logged in. We will start that by creating a described block. In it, we can write whatever text we want. We'll call it homepage, you can name it whatever. I'll just do a function and open that up. This is my described block. Now I need an int block. I'll say should load, sure. And now I'm gonna do an asynchronous function. We need that cuz we're gonna use the await keywords. And now we have our two block set up for our first test. First thing we need to do is load the home page, so I'll do await browser.url. And instead of entering the entire URL, I can just do.slash. In the book, I talk about this a little bit. Let me see what I do. Yeah, I go there. Let me see. Yeah. Here's what I want to show you. So say you have a base URL of example.com slash one. So this is my base URL in my configuration. If I do dot slash two it's going to append two to the end of that base URL. If I did just slash two then it goes to the root of your URL, example.com, so it gets rid of the one and then appends two. Alternatively if I enter the full URL, it's going to ignore your base URL entirely and go to whatever that URL is. So it's a little important, dot slash appends it to whatever is in your base URL, slash takes you to the root and then if you just hard-code the whole thing in there it takes you there. So for our test we can actually, we could just do slash, we don't have to do dot slash, but for whatever reason that base URL might, like say you're on some public server and you You have your, your project, the root of your project is in a folder You don't want to have that folder shipped out, so we'll just do dot slash here So that's going to load the browser. Now one thing I don't talk about in the book which I really wish I had time to is browser debug command. This is a very useful command for pausing your tests in the middle of your test and seeing what's going on. So basically what this will do is just stop running your tests. It won't shut your test down it'll just pause them until you finish So let's run that. So now I'm going to do npx wdio Wdio Fingers crossed it works I'm not actually crossing my fingers. I should be Selenium standalone exited before it could start. Okay. I want to debug this. Let's debug this Because this is the value of going through this as a workshop together is You get to feel the pain my videos. I don't really make you feel the pain because I don't think you should feel pain in videos Yeah, that doesn't give me any extra information I Don't have any logs or anything. I think what's going on is I don't have Java installed I Wish it gave me a better Answer than that. I'm going to try something I'm going to do NPM I Let's install selenium standalone Globally so that's what that dash G does it installs it globally that way I can run Selenium standalone Start oops So this is how you run it globally You install it globally and now you have a command line tool that you can run there's install and start Install will install you see it's installing chromedriver It's installing the hub Gecko driver for Edge driver Now that those are installed I can run selenium standalone start and this should fail Yeah You see here. It actually gives me a real answer as to why it failed This is that error from before that we were seeing But this is the actual issue is that we don't have Java runtime installed so I Don't want to spend time installing Java runtime So instead what I'm gonna. Do is npx WD io install service Chrome driver, I'll just fall back to Chrome driver Isn't that great you like? Having to debug these issues The only way I know this is Just that I've done this enough, and I've been burned enough that I figured it out But yeah, there's no special thing that I knew confident service property Hey look at least it gives you all the ways to install it. What did I do wrong? Couldn't find the service property Really Oops I don't know my command line enough Why is it saying that I have it right here Let me try that again Oh, okay There installed it it updated my configuration file So if I go back to my code you see now it's got in chrome driver One thing that it said is please change your path to this. I didn't get to it. I was kind of forgot about it But I think it's at the very top No Where are you? Oh, it's not in here No, okay, I Don't think it's necessary. It's telling me to change the path in my configuration file oops To be just this I think this is the default so I don't think we have to set that for Selenium standalone We go back in here under services And There you can do command K or Alt K maybe on Windows, and that'll bring up this search box whatever that thing is and you can search for it so In here Where do they have it? It looks like they don't have it anymore Used to have to set the hub in the path But it doesn't look like you have to set that anymore. So that's pretty nice That's why it wasn't in our maybe it's the port Something like that you just have to set that it's in the book. I'm pretty sure so I need to update the book But it's nice when you don't have to do things It's unfortunate for you cuz I still explained it to you and kinda wasted your time there, but it's nice for the future Okay, I've got Chrome driver installed. I can just run npx WDIO again Now it's running now. It's paused So this is our debug right here the execution has stopped You can now go into the browser or use the command line so I can actually run things like get title and Now it ran the browser get title command. I could do browser dot get URL and This is the result from there. So you see it logs out what it's doing And then the result with these logs. I don't want to get too much into it What it's doing and then the result with these logs I didn't really explain these logs, but the way that web driver io interacts with these browser drivers Is if you're familiar with website apis web driver? Web driver not web driver. I oh Web driver which is the specification? So Chrome Driver runs a web driver server Web driver iO Sends an API request to The server We'll talk about this in just a second So here it sends a POST request to my web driver server With this specific endpoint in this case the URL end point This ID here is the ID of the browser That is running. So that's your session ID That's going to change every time and then This is the endpoint. So we want to hit the endpoint the URL endpoint. We're posting data This is the data that we're posting. So we're posting a JSON object With that has a property of URL and that's the URL So that was our command. This is the WebDriver IO. Well, this is the WebDriver spec command I think That's being run and Then this is the API request.
12. Debugging and Timeout Configuration
This section explains how to debug WebDriver IO tests and adjust timeout values. It covers the use of the debugger, setting timeout values in the configuration file, and handling Selenium server timeouts. The debugger is a helpful tool for pausing tests and inspecting the browser state. Timeout values can be adjusted in the configuration file to allow for longer debugging sessions. Selenium server also has its own timeout, which can cause tests to fail if not properly configured. The section also mentions the use of selectors and the importance of choosing stable selectors to avoid test failures when UI elements change.
This is the data that goes along with it. We don't get a response but if we did get a response You would see the result here So the response here it is the result and in this case, we asked for the title So again our Chrome driver and our chrome driver server session with the session ID The endpoint of title and we get it's a get command so we don't send any data This is the result returned and then this is just logged out Once again get URL Goes to the URL endpoint Instead of a post command or instead of a post action It's sending a get and this is the result that comes back to it. This is helpful to know for For when you're debugging and you will kind of want to understand what the browser is doing You kind of read it like the matrix this 0-0 They're not just eyes looking at you They can be 0-1 0-2 that is when you're running multiple tests at the same time That's the test session. So Yeah, you'll sometimes see 0-1 0-2 0-1 0-1 That's just that browser session is hooked to that So that way when you have like five tests running at the same time, you need to debug one of them You can look for just those specific ones so what happened here is We restart timeout Mocha waited 60 seconds for something to happen Nothing happened. So it shut down the test and failed it That's where that debug that we had talked about really comes in handy Because sometimes you want more than 60 seconds to look through an issue So I'm gonna go back into my configuration file. I'm gonna come back here to this timeout and I'm gonna paste in that code Now I can set my time out to be longer if I need to so I'll go back to my command This is definitely going to be different for windows than mac OS But for Mac OS or Linux you can just set the environment variable you want to change in this case debug we want to set it to true This is just gonna be string And then we'll run our command so when it gets here, it's gonna check that environment variable see that it's set to true and Set it to a very large timeout I think in the book. I cover how to do that on Windows, but now it's paused again in our debug I Get to that chat in just a second. So now it's paused and now it will stay paused for a long time Okay, you didn't give it a soul is selenium different. No, it should be the same thing I think what happened came execution timed out is maybe when you ran that I Don't know how quickly you ran that but it might have timed out in between Sending the command and Seeing a message from it. They're also yeah selenium selenium has its own Time out value as well So there's multiple timeout values Just a second I'll paste that in If we go back to our configuration test run a configuration Actually We see So there's a mocha timeout so mocha is default to 60 seconds, we're overriding that in ours There's also a selenium timeout. So the selenium server will shut down After a certain amount of time, so I think what probably happened Was your selenium server shut down? Trying to see if it's in here No Oh I think somewhere in here there's a timeout value. I can't find it right now. Yeah, so I think what happened was your Selenium server shut down before you ran that command, which is a, it's a different timeout. So somewhere in here you can set the timeout for Selenium specifically. But basically if you go a certain amount of time without sending a command to Selenium, Selenium be like okay well I'm shutting down this session. 10 seconds to get the debug code. Yeah, I'm kind of confused why that happened. Okay, to exit out of here you can do.exit or you can do control C, and that'll exit you out of the debugger. That's the debugger, very helpful. It drops you into a REPL. I mentioned that that WDIO.. that REPL service. That didn't work. Oh, that didn't work. I think I have to add more information. Yeah, I have to add more information. So that's that's a.. I really like that bit of functionality. It's helped a ton because you're like in the middle of a super long flow. You want to get.. see exactly what the browser state is at. That's what that's for. Okay, so we ran the browser dot get title so I'll do let's assert on that title. So we'll do wait, expect browser to have title and we'll just do conduit. You see there was to have title containing as well. We actually don't need to do it. It does help if I spell it correctly. So we can run this quick assertion. We're passing in the browser. We do not need to await inside of here. So I don't need to do that. Because expect will automatically wait for this to return. And then this is just the to have title assertion. So just double check that works. Let's give that a shot. Get title of result conduit. What did I do wrong? I misspelled it again. How did I do that? Was it right and then I got to be wrong. Okay, so now it loads. That's great. So that's the start of our test. Very simple test. Let's add a little bit to it. So the next thing we want to do is click a button. In this case, we wanted to click the sign-in button. So let's inspect this. There are several ways that we can click this button. And this is where we get into selectors. So you can use any CSS selector and by that we can, down here in the very bottom if you can see it, we have our selectors. So if I select every A element on the page. Oh, that's not what I wanted. Okay. So we'll go ahead and select that. Or we can also, we can also click let's see I want to do a class of nav link. So you see it highlights this. It's very bottom of the. I've got a class of nav link, but there's four of them. So I don't really want to use just the class of nav link. I could specify a link with the class of nav link. That doesn't really change much. I could actually get this attribute. And this isn't web driver IO here, this is just CSS. So here I have a anchor tag with a class of nav link that has an href attribute of slash login. That works. And that would, I could go back into my test. And I'll do my await. And I'll do the dollar sign because I want to select an element. I'll paste this in. And then I'll run my click command. And this will work. This will click that element. But I hate this selector. This selector makes me angry because it's so, it's too much. Like this class name gets changed for whatever reason, which can happen. Say a new UI framework is used and it's not nav link anymore, it's menu link. Now your test fails. Maybe the H ref has to change or maybe it's no longer a link. Maybe it's a button. Again, your test fails. So that's I don't like this link.
13. Using Selectors in WebDriver IO
We can simplify it by getting rid of the nav link and using the text of the page itself. We use a special selector in WebDriver IO called the link text selector. It allows us to select an element with specific text in it. We click on the sign-in link, but the page title doesn't change. Instead, we check that the URL contains 'login'. Using the actual text of the content or adding custom data QA IDs in the HTML are good practices for selectors. Selectors may change, so it's important to make them as bulletproof as possible. We can break assertions to ensure they are working correctly.
What we can do, we can simplify it so we could get rid of nav link. We don't really need that. Just basically any link that goes to login. Or we can actually just use the text of the page itself. I like using the text of the page. So here I will just do sign in. I'll do sign in. But it's not that easy. It's a little bit more complicated. What we have to do is put an equal sign there. This is a special selector in WebDriver IO. This isn't CSS. This is WebDriverIO. And if we go to the WebDriverIO pages, they have an entire page on selectors. And they have one that's the link text selector. It allows you to select an element with specific text in it. Paste that over there. Here equals WebDriver IO. So if we have a link that has the text WebDriverIO, then we can get that element by that text. There's more we can do with this, but let's move forward with just this special selector. So again, this is WebDriver IO specific. This isn't a CSS selector. If I tried this back here, very bottom equals, let's sign in. It doesn't know what to do with that. It doesn't have a clue, because it's not CSS. It's WebDriver IO mostly. So we're going to click that. What happens when we click that? Let's go back here. I click it. Look at this page title. Notice it doesn't change. That's an issue with a website, kind of a bug. So we need a different assertion. We want to check. Ideally we would assert that we're on the sign in page, so our title would say sign in. But that doesn't happen. Let's just check that the URL is log in. So we could also check that this element exists. We can check that the form exists. You can do a lot of stuff. You can check that you're on the auth page. You can do a lot of stuff. We'll just check the URL. So now we'll do another await. And we'll do expect browser to have URL. But we don't want to check the entire URL. So what we could do is we could check this entire URL. But you see we've got localhost here. How do we know that we're on localhost and not on the demo site? So instead of having URL, we're going to have URL containing. And we're just going to check that it has the URL containing login. Now I'll run my test again. Should click that sign-in, but it didn't. You know why? Because I made the same mistake 50 times, and I'm never going to learn my lesson. It's not a capital I. It's a lowercase i. Try it again. Would accessibility props be recommendable? Are they good rule of thumb? The main thing I want to look for with selectors, are is some programmer working on the code who doesn't know about my tests, are they going to change the code and break my tests without me knowing and without them knowing? So, using the actual text of the content is pretty good, because that's less likely to change in theory, although people tweak stuff just for like A-B testing. Something else I showed you are these data QA IDs. If you can edit the HTML, I really like adding these in here, because who's going to change that? Hopefully, nobody is messing with something that says QA ID. And so, this is kind of like an ID attribute, but it's custom data attribute. You can rename QA to be whatever you want. Sometimes I'll use type instead of ID, and that kind of maps like a class name. But anything after data dash is totally legal in HTML 5. So, go for it. I've always gone with QA ID. It's short kind of gets to the point if you're familiar with what QA is. Yeah, text does change, actual component's change. Yeah, accessibility in theory shouldn't change much. But, you know, I think you have to do as good as you can with making your selectors bulletproof. But they're going to change and you're going to spend a significant portion of your time just keeping them up to date. So, having them break as least often as possible is what you're going for. Okay, we had our test passed here. One thing I really like doing is breaking my assertion. So, here's something. Say we forgot to put the await in there. Let's see. Actually, I'm not entirely sure. Yeah, there we go. Excellent. So, it still shows it's passing. If we go back to our test, it shouldn't have passed. It's not going to have log in in our URL. But it passed because we're not waiting for this assertion to go through. So, that's one thing I like to do when we're trying to break things up. So, now, that's one thing I like to do when I'm writing my test is let me make sure that it actually fails. So, here I took out the O in login. This test should fail. And now you see it's failing because it's waiting for it to be login. No, sorry. It's waiting for it to be login.
14. Selectors, Drag and Drop, and Actions
You can log out your commands if you want. Anything that comes through there. In the next part of the book, it talks about selectors. So let's look through this selectors page real quick. You can select multiple elements using double dollar sign. There is a drag and drop command, but it's tricky. There is also a perform actions command that is really powerful. You can queue up a set of actions. The documentation for it isn't great unfortunately. We'll run through the selectors real quick and then test the sign-in page and look at the issues you might encounter.
But it's only coming back with login. So, make sure your tests fail when you're writing them. And that's our first test of the site. Take a pause and one thing I'm going to do is go back to there. Give you all time if you've got this test running. I'm going to make sure I didn't pass over anything. If you ever want to see what the result of the command is, you can just log it out like that. And you'll see that we actually have a command.
Ok cool. Go back to there. So yeah, you can log out your commands if you want. Anything that comes through there. Assertions, we kind of skipped through. In the book I talk through different ways that you can write assertions and how assertions kind of function beneath the hood. But we are going to skip past that. In the next part of the book, it talks about selectors. So let's look through this selectors page real quick. So you've got your CSS query selectors. Again, anything you can write in a CSS file. You know what I'm going to do. Let's switch this mode over. There we go. A little bit nicer on the eyes maybe. So anything you can do with a CSS selector, you can do here. There's also... I haven't mentioned it yet, but you can select multiple elements. So instead of dollar sign, you use double dollar sign and that will bring you back multiple elements. So here they want to get every element in this menu. Let's see. So yeah, they do some crazy stuff here. That's a crazy example. I don't know why they go so into the deep end there. But basically, if you want to get all the links, you would use double dollar sign to get all your links. So that kind of maps up to... who mentioned it? Okay, so we do that. Query selector all. That's essentially what the double dollar sign does. You can do Query selector all. There was another question that I mixed over. Do we have access to low level interactions like hover, focus, drag and drop? You do. There is a drag and drop command. I haven't used it much. It's tricky. In theory it's as easy as this. You get the element you want to drag, what you want to drag it on to, and then do that. In theory that works. It really depends. Otherwise you can move it from a specific position. But that's the extent of the examples. Unfortunately they don't have more examples. There is also... what command is it...it's like an actions command. There we go. There is a perform actions command that is really powerful....Oh where did it go? Perform actions? Fortunately there's no command to import....Oh where did it go? Perform actions? Fortunately there's no good documentation for it, ... But you can queue up like a set of actions, like here. These are all my actions that I want to take. Move the pointer, click down, hold it, move it, click up. That's my first action. Then my next action here. The pointer is just a touch pointer. A one second pinch and zoom with half a second waiting after the finger's first touch. So you can put together some really complex actions in here. So I'll start by doing control S. We run on the keyboard key down for control also for S. Then we lift control and we lift S. If you want to check when you press Control S that it pops up the save window or something. Or it saves the file. That's how you do it. So that is available. The documentation for it isn't great unfortunately. It's one of those things that I wanted to cover more. I just haven't gotten to actually understanding it. But I think in actions... Yeah. You just pass in that object that was shown in the spec. And you can do that with like cover like cover stuff. There's also mouse. Being weird. Any questions before we get back into it? Yeah. Go. So what we'll do is run through the selectors real quick. Then we're going to test the sign-in page and take a look at some of the issues you might run into with testing the sign-in page and how you can debug them and fix them ideally. Close some of these we don't need them. What's that? Oh. Don't need that. Close that. And close that. And close that. Keep that open. So you've got your CSS selectors.
15. Selectors and Sign-in Page Tests
We've covered the link text selector, partial link text, chaining selectors, and selecting different types of elements. WebDriver.IO provides specific syntax for selecting elements, including the use of XPath selectors. XPath offers more flexibility than CSS selectors, especially when selecting elements by text. The Elements pane in Chrome Developer can be used to test and experiment with selectors. There are also other selectors available, such as accessibility selectors, JavaScript function selectors, and mobile selectors. Custom selector strategies can also be added. Finally, we will write tests for the sign-in page, including scenarios for entering valid credentials, missing email, and missing password.
We've also covered the link text selector. You can also do partial link text. So if you only wanted to select it by part of the link, you do a star equals. You can also can't do this. So you can't use a CSS selector mixed in with a partial link selector. You have to do them differently. You can chain them together, though. So I want to get the element with a header. And then I'm going to look inside there and find the link that has the text driver inside of it somewhere. That's what's going on there.
Now what you can do is, those were all for links. But you can actually pass in a different type of element. So say you want to select a h1 with the text of, welcome to the page. You can do h1 equals. This is very specific to WebDriver.IO. I think this actually converts it to an XPath selector, which you can use XPath selectors. You can see there's some complexities to that. Tag name, that's just, I rarely ever use that. Name attribute, kind of the same. Anything XPath you want to check out, you can use. So I use this. Sometimes there's this cheat sheet, XPath CSS selector cheat sheet. Let's see. This cheat sheet, very useful. I use it quite often. It'll show you the CSS selector with its XPath companion. Now, there are some things that CSS is better about, so selecting by class names. XPath has some issues with it, but there's some things that you can do in XPath that you just can't do in CSS as far as I know. Those are getting things by its text, specifically. I don't think CSS has a text selector yet. You got contain, starts with, ends with. You can move around. So you can say, I want the following li of ul. Yeah, you can go to a parent, so you can go up a note if you want to. There's a lot of cool stuff you can do in XPath that isn't quite there in CSS. One thing I was showing you this selector here in the bottom, you can actually select by XPath as well. So if you want to use a CSS selector, you can do it. If you want to use an XPath selector, you can do that as well. So you get to that by going to the Elements pane in Chrome Developer. If you're using Chrome, in your Developer Toolbar, hitting Command F, or Control F if you're on Windows, and then whatever you want for your selector you put in there. So that Cheat Sheet is pretty good. There are other selectors. There's your accessibility selectors that you have like ARIA Label. Those are actually kind of new, which is nice. You can actually use a JavaScript function. That's kind of nice. There are things for the Shadow DOM if you're working in React. There's some functionality around there. I won't really get into it, but I think maybe it's that that does it. Mobile selectors if you're on Appium. You can also chain selectors together. I already mentioned that. But basically if you need to, you can chain them together. And more React selectors here. Then you can even add your own custom selector strategy if you want to. Added selectors. That's all selectors. So you have a lot of options there. A lot of power there. Interacting with stuff like face ID. I don't know. I just don't know. Yeah, that's outside of anything that I've gotten into.
OK, the last thing we want to do, I think, is test this sign-in page. So we're going to write a new test. Go here and go back to our code. Pull that out. Close that file. Close that file. Create a new file in our specs. We'll call it login.js. So that's what I called it. And I'll set up my new Describe block. I'll call it the Login page. Actually, what I'll do, so I have my login page. One thing that I like doing when I'm writing tests, is writing out what the tests are before actually starting on the test. And I think that really helps me make sure that my tests apply to specific requirements and that I'm not just writing tests for the sake of tests. So here, what I want to do, there's a few things I want to test. I want to test that if I enter a good email and a good password, it lets me sign in. I want to test that if I enter just the password, like this, it gives me an error that the email can't be blank. If I do just the email, sure, let's see. If I can't fool it, that it tells me that the password can't be blank. So those are the three things that I want to test on this page. I could actually test more. And I'll just say, should, let me. In with valid credentials. Sure. Sure. If you notice that should is still in there.
16. Writing Test for Login Page
I want to write tests to go to the login page, enter a username and password, click the sign-in button, and assert that we're logged in. It's important to keep the scope of the test focused and avoid testing unnecessary functionalities. By directly going to the login page, we save time and prevent the test from becoming brittle. We can use selectors like 'placeholderofemail' and 'password' to locate the input fields and set their values. The 'Sign In' button can be clicked using a partial text selector. To ensure that everything is working correctly, we can pause the execution for a few seconds. This test will help verify the login functionality of the website.
If you notice that should is still in there. Should not. Should show error with username. And I'll copy that. And should show the error with a missing password. So these are going to be the tests that I want to write. Now I have a good sense of what I want to get written out there. Just a second. OK. Come back here. Now I'm just going to convert this to a test. So I'll say it. Let's see if I can do this. There we go. And we're going to do async function. And I misspelled function. Of course I did. There we go. Now I'll do the same thing with my test. I will comment in what I want to write for my test. So first thing, it should go to log in page. Then enter user name. Password. Click sign in button. And then assert that we're logged in. So now I have basically an outline for what I'm gonna write in my test. Step one is let's go to the log in page. So here I'll just do my await, I'll do browser.url. I could in my test, I could have it go to the homepage and then click sign in to get there. I don't wanna test that though. One of the big issues with automated testing is you. It's so easy to write to test more things than you need to be testing. In this case if I go to the homepage and then click the sign in button, I'm not just testing the sign in page. I'm also testing that the sign in button works. So now the scope of my test has increased. Now the chance that my test breaks has also increased. And it just makes very brittle tests. So try and keep the scope of your test down as much as possible. The other thing is that it takes a second to load the homepage and then click the sign in page. Let's avoid that extra time. So I'll go in here. I will do.slash for login, and we'll wait for that. Then we're gonna enter our username. So here I'll do a wait. I'll do my dollar sign for my selector. Let's figure out what this needs to be. I will inspect my email element. So we have. We could do the placeholderofemail. There's no id on here. There's no data id either. So we could add a data QA id. I'll just use this attribute, placeholderofemail. So let's go in here. I will do input placeholderofemail. And that'll be my selector. Really, ideally, you use a data QA id or maybe an accessibility id. The other thing to mention is if you do Appium testing, there's another thing called an accessibility id that's different from ARIA. ARIA is for the web. Accessibility ids are something that Mac and Apple came up with. And they're different. So just be aware of that. This is gonna be our selector for the sake of time now. We'll just call setvalue, and we're gonna set the value to demo at learn. driverio.com. And I will paste that into chat for everyone. You could leave out the input if you wanted to. You could also use the type. I'll show you in just a second. So we could do type of email, which matches up here to this attribute. That's another option. You can select elements in 100 different ways. Okay, let's do the same thing for the password. So, we'll just do that same place holder. And now we'll do password, and our value is going to be 102. That's a great password. I'm gonna keep movin' on. Next thing, click the Sign In button, because we've kind of already done a lot of this. So, we're gonna do await. Let's see, what is this? This is a button button. Text of Sign In. So, let's use that element with partial text selector. Let's see, Sign In. Double check, get lowercase i, Sign In. And then, all I'm gonna do here is let's pause for three seconds. Ah! So, there's a browser dot pause command that just pauses execution for however long you say. Here, I'm saying three seconds. We're not gonna assert this yet, I just wanna make sure that all of this worked. Okay, so I wanna run my test, but I don't wanna run both of my tests, because I know my other one is working. I'm just focused on this specific one.
17. Running Login Page Test and Debugging
In this part, we set the spec to 'login' and run the test. We encountered issues with the password and missing click actions. We discussed different ways to assert that we're logged in, such as checking the form, menu, URL, and feed. We highlighted a bug by testing incorrect user credentials and validating the absence of an error message. We observed that the selector was correct and used the debug mode to troubleshoot. We discovered that the issue was caused by the API request not being triggered immediately upon clicking the sign-in button.
So, I'm gonna set my spec to equal login, because that's the name of my file, login. I don't have to pass in the folders. I don't have to include.js. This will match, fingers crossed. It will match the right login file, there we go. Okay, so, let's run that one more time, because I was kind of distracted. Yeah, so it didn't actually take us to anything that we wanted it to. Let's look through these commands. We enter our password here, we find the element, button contains sign in. We found an element. Oh, did I never click on it? Uh-huh. It helps to actually do the action that you want. That's right, that's not the right password. It's actually wdio-demo. Try it one more time. There we go. So you saw it logged us in. Now we need to, yeah, I missed the click. So, let's do that here. Demo at learnwebdriverio.com and then it was wdio-demo is the password. So, there's a lot of things that we can, what we wanna do is assert that we're logged in. There's a lot of different ways that we can check that. Just a second. Look through all the different ways. We can validate that the form, that login form is gone. We can check that this, see this menu up here has changed. The URL changed. We're on the global feed and that we have a your feed. This conduit is here. If you wanna log out, you go to settings and then log out, then you can go back to sign back in. There's a lot of things we can do and really, it's up to you how you, what you wanna specify. For our example, there's a specific thing I want to do because it shows off a bug or maybe not a bug but a potential issue in writing your test and I wanna highlight that. So what I wanna do is check that, say we enter, I don't know what I'm typing, an incorrect user and password. We click sign in. We wanna validate that this message doesn't, does not exist. So what we'll do is, let me see how I did this, I'm just gonna copy and paste this code in. So we'll get rid of our browser pause. We're gonna do our assertion, await, expect. What we're gonna do is we are going to pass in an element which is something that we can do and that element is going to be this error messages LI. So we're gonna do.error messages LI. So we're gonna look at this element and what we're gonna do is we're going to expect it not to be existing. So if you remember there was a to be existing assertion that we had from our example while back. There's also not to be existing, which does the opposite. Basically, when I click this button, I'm expecting it to take me to the homepage. If there's an error, then this element will show and it will be existing. And if I reload the page, let's come up here. You can see there is a error messages UL, but there's nothing inside it. So that's what we're expecting is not to have that element on there. Let's run that. And we should have a passing test, good. Now we're gonna do the thing where let's enter a wrong email. Now we should expect this test to fail. It did not fail. Did it not do our assertion? No, it checked here. You see we're going to find elements with our CSS selector, posting it, didn't return any elements. Maybe our selector is wrong. Let's copy that selector over back to the browser. Enter bad email. Now that's there. I paste that in. It's finding it. The issue is not that the li isn't there. It should be there. In fact. Let's do something. Let's do our debug. I'm not gonna put the debug code on there cause it should be pretty fast. Okay. It's there. This is where you start to lose your mind. I mean I can even pass in that is existing. And you see it's true. If it wasn't existing, it would be false. So what's going on? Well, let's slow things down. I'm gonna refresh this page. I'm gonna go to my network and I'm gonna throttle it. So I'm gonna slow down how fast the page loads. I'll clear this out. So we'll do our bad username. Type it correctly. Bad password. I'm gonna click Sign in. Watch here. That's how we've clicked it. Nothing has happened. Now it shows. What happens is when we click the sign in button, it actually sends a API request to login. There's our API. With a... Here.
18. Handling Error Message Wait Time
With our test, we're not waiting long enough for the error message to exist. There are some other ways to handle this. We can change our assertion to be more accurate.
With our email and password. It waits, I don't know, two seconds for it to return. And then here's the error message and now it shows the error message. With our test though, it's clicking sign in, it checks to see if it's there. That response hasn't come back yet. It says, oh, it's not there. Great, we passed. That's what's going on here. We're not waiting long enough for this error message to exist. There's some other ways. Remember I said that there's auto waiting? Well, the thing is you can't... Ugh, it's just weird with how this is set up. Ideally, this element never exists. The problem is that it starts off not existing. Now you could say something like to be existing then it would wait. But you don't want this element to ever exist So it's just something weird with that. And what you can do is you can change your assertion to be a little bit better.
19. Improving Test Waiting Time and Custom Waits
To improve the waiting time in tests, we can use the throttle command in Chrome driver to slow down the execution. By adding a custom wait using the wait for exist command, we can pause the test until a specific element appears or disappears. We can also use the expect library to check for URL changes. However, support for network intercepts is currently limited. It's important to choose stable selectors and avoid relying on timing-based assertions to ensure reliable test results.
Another way is you can just cheat. So, let's wait one second. So we're going to click the button, we're going to wait one second, then let's check it. So I still have my wrong password. Let's run it again. Still passes. That's kind of weird. Oh, because I changed it. It passed because it did what we told it to do. There we go. So now it's failing. Now it sees that element there and it's like, oh, that element shouldn't be there. I'm going to keep waiting ten seconds until that element disappears. The element hasn't disappeared so I'm just going to throw an error. So we can do that, but that's not great. Because what ends up happening is your tests just become really slow. And the problem still exists. It's just you've waited enough time for most of the time the problem not to exist. But that's really bad because you end up in a situation where you push this out to like a CICD server and now your test is failing because it takes longer than a second for that API response to come back and now you have to debug that. So we need a much better way of doing this. But before we get to there let's go back to our configuration file. If anybody needs me to show anything, just let me know. I'm going to go down to my before hook and in Chrome driver there's this really cool throttle command. So, if you notice on my network here I went to the network tab, I changed the throttle to be slow. We can do that in our code itself. So, there's a throttle command and we can do is just copy this code over and in our before paste that in. I need to add a sync to it. Latency, let's up this latency to one second. So, this should just do one and a half seconds. This should slow things down. I'm adding it to my before command. I don't actually have to. I could just put this in the test itself. I just kinda wanted to show how you would add it to your command. Now, before I run this, I have had this fail on me multiple times, so if this doesn't work, I won't be too surprised. It looks like it's, see how it's loading slower? Definitely loading slower. Oh wow. Okay, I may have slowed it down a bit too long, but what we should see is that it enters the wrong email, the wrong password, and our test passes. And it shouldn't pass. We still don't have that correct email in there, or the correct password in there. And see, our browser paused, just, it didn't work. Didn't work for our browser pause. So what we need to do is instead, add a custom wait, to say, wait for something to happen, and then run our check. I'm trying to remember what it was that I waited for. So give me just a second. Basically be anything. Okay, so what we'll do. I wonder why I did it like that. I don't want to do that. I want to wait for, since we're low on time, I want to wait for this sign in button to disappear. No, so there are in our elements, there are these wait for commands. So here we have wait for exist. So this will basically pause the execution of your test until this thing exists. Could also wait for a URL change. That's not a bad idea. That would be using a custom wait until. There's not like a wait for a URL. Although we could, one of the things is when I wrote this, that expect library wasn't out. That has some wait for stuff in it. And so I made the example using this, and it turns out that you really don't need to do that. You can use expect browser to have URL not having that log in. Anyway, it's just one of the, they add new features that make the thing that you were talking about obsolete, and it's really great. It's also really frustrating. But let's use this wait for exist. So when I did my login, actually I'll log in here. See this new, or actually the settings link. We can wait for the settings link to appear. This is kind of weird because why are we checking the messages if we're already on the page that we want? But humor me. So this is just gonna be a link. I'll just do star equals settings. And I'll wait for it to exist. The other thing I'm gonna do is I'm gonna speed this up just a little bit. That was a little bit slow. Now we'll run it. And now our test should pass because it's always waiting for that response to come back. And ideally, this is where network intercepts would come into play. Support for that's kind of missing. So you see it's checking for the settings here on the right, and it's not finding it. Thing is, it's gonna throw this settings error. So it's not even getting to this assertion by that time. So you don't really need this assertion really at that point, you could just have this be your assertion. So we could really just change that to be to be existing, and then make this be expect. But I needed to show off how to do it the other way. So you could do that as your assertion instead. And I want to show off one other thing, is to reverse it. So maybe, I mentioned waiting for the sign in button to disappear. How do we do that if there's only wait for exists? Well, it's you tell it to reverse it. So if you set reverse to be true, then wait for exist will actually wait for it not to exist. You can't do not wait for exist, but it's kind of the same idea. Oh, I should update my selector, because we're not waiting for settings not to exist.
20. Reusing Selectors and Variable Declarations
We can reuse the sign-in button selector by storing it in a variable. No need to use await when setting the variable. WebDriver IO allows for easy reuse of selectors. My semi colon usage is sporadic, apologies for that.
We're waiting for the sign-in button not to exist. So that's how you flip the wait for and there's a couple other options in wait for as well. One quick thing that we can do, see how this is the same code here and here. Well, we can move that to a variable. So I'm going to do const sign-in-button equal to sign-in-button. Now we only have that selector here once. So if that selector ever needs to update it, we only update it in one place and we can reuse it. Note that we do not use await when we're setting this. We don't need to because this await covers it. So that's just something to be aware of. You do not need to await. I don't think it's going to hurt if you do it. It should still work. It's just not necessary. But now we can reuse that sign-in button wherever we want. It's one of the nice things about web driver I O is that allows you to do that. And I'm sorry that my semi colon usage is so sporadic. I can't break out of the habit.
Comments