Auto-Waiting Mechanism | Bondar Academy
Course: Playwright UI Testing with TypeScript
Module: Locators and Assertions
Instructor: Artem Bondar
Lesson Summary
In this lesson, we discuss the auto-weighting mechanism in Playwright, which enhances test stability by automatically waiting for elements to be visible , stable , and clickable . Understanding the nuances of this mechanism is crucial for effective test execution. Key Concepts The await keyword is essential when working with Promise methods in JavaScript, allowing tests to wait for specific conditions. Playwright methods automatically wait for conditions such as: attached visible stable receives event enabled editable Default timeout for these waits is 30 seconds , which can be configured. Examples of Auto-Waiting For instance, the text content method waits for an element to be attached before retrieving its text. Conversely, the all text content method does not wait, potentially leading to flaky tests. Alternative Waiting Strategies For methods lacking auto-waiting, you can implement alternative waits, such as: await page.waitForSelector(selector) - waits for a specific element. await page.waitForResponse(url) - waits for a network response. await page.waitForLoadState(state) - waits for the page to reach a specific load state. In summary, Playwright's auto-waiting mechanism simplifies interaction with web elements, but understanding its limitations and alternative strategies is vital for robust test automation.
Video Transcript
In this lesson, we will talk about auto-weighting mechanism in the Playwright. This mechanism is very powerful and helps you to make your test more stable. So Playwright will automatically wait for your elements to be visible, stable, clickable, and so on, so your test execution will be more stable. But those rules have a certain nuances that you have to understand in order to know how those rules are applied to your code. So in this lesson, you will learn about this. Let's get into it. So earlier, we talked about the keyword await that you have to use every time when we work with the promises types of methods. And promise is a type of the JavaScript function that can wait for the certain desired condition up to the limit of the timeout. And this concept is used by Playwright to wait for the web elements to be available on the page and interact with them. So this happens automatically. For example, text content method is waiting for this basic form button to be available. So it can take the text from this button, and then we can make assertion of this button. Same for the click. So click is also waiting for different conditions for this basic form button in order to perform the click. And the default timeout to wait for this condition is 30 seconds, which can be configured. And about the timeouts, we will talk in the next lesson. In this lesson, we will talk just about the waiting concept. So what are those conditions? If I go to Playwright documentation, here is the article, auto-waiting. And conditions that Playwright methods can wait for are attached, visible, stable, receives event, enabled, and editable. And here is the table of all those methods. As you can see, not all methods wait for all the conditions. For example, click wait for attach visible, stable, receive events, and enable. But for example, method text content wait for only attach. And if element is not visible for some reason, this method will be executed. And also you can see that number of the commands that support auto-waiting, it's pretty limited. For example, this list doesn't have the command that we already used, this one, all text content. Even it is a promise, we see this is a promise type of the command. This command will not wait for any condition, it will just run the test. And if some locator is not available or not visible at the time when this command is executed, this will create a flaky and unstable test. So and let me show you how to deal with auto-waits and all those kind of conditions. For that, we're gonna use a different website to test. This is a uitestplayground.com, and it has just a nice button, which I click on this button, it has a 15 seconds delay. And after 50 seconds, we have a message data loaded with AJAX GET request. So we will try to interact with this button that have this text. And using this example, I will show you how Playwright automatically waits for this button and for this text to be available. So for more convenience, I will create a new test file and call it auto-waiting.spec.ts. And we'll set up a brand new test suite. So I made the import, then I need a before each section. In the before each, I'm gonna put my URL, which is this one. And also what we want to do is click on this button, right, inspect. And this is the text we want to click, get by text. Instead of forms, we will click on button triggering AJAX request. We want to make it before every test. And then the test itself. So the first thing, let's find the locator for the section of the success message that we want to interact with. So let's do this BG success class, and we create a new locator. And I will call it successButton equals to page locator.bg.success. And now let's try to just simply click on this button. SuccessButton.click. And I will run this test. Playwright runner. We have new test shows up, and I'm running this test. So you can see right now, Playwright is trying to perform the click, but the button that we are waiting for is not available yet. And Playwright patiently wait up to 30 seconds for the success button to show up and to perform a click. Here we go, button shows up after 15 seconds, and click was performed. We can see that this is successful. If I will forcefully reduce the timeout, so I go to my Playwright config file. And here in define config, I will change the default timeout to 10 seconds, which is 10,000 milliseconds. And I'm going back and running this test one more time. Now we see that click command is trying to access this button again. And we can see the error message waiting for the locator, bg.success and target closed. So conditions of the click command were not satisfied within the timeout of 10 seconds. It was trying to perform the click on the button, but button was not available within 10 seconds of the timeout. So let me show you something similar. I will change this timeout back to 30 seconds. And the second example is with text content. Await success button, text content. And let's create a constant, const text. Equals to, we want to grab the text from this web element and then create assertion, expect text to equal. Data loaded with AJAX. And we can see that this is successful. Data loaded with AJAX get request. So I command out this line of code and run it one more time, running it again. Yeah, and you can see the same thing happens. So text content is patiently waiting for this button to be available in order to grab the text from the page, and when it will be available, it will make this interaction and test is completed. So you can see here, this is the step that performed for 15 seconds, and then we perform the assertion. So this is how auto waiting works. But let me show you a different example. When we use not text content, when we try to use get all text contents, I will comment this code and run it one more time. And we can see that it is failed right away because all text content did not wait for the text to shows up. We see expected data loaded with AJAX but received empty, simply because all text content didn't wait. And what we can do about it, we can create additional weight for the methods like this, which do not have implemented auto wait logic. We can do something like await success button and we want to wait for a certain condition. And let's say that we want to wait for a state which is attached, detached, hidden, or visible. We want to wait for state attached. And if we run this test one more time, now you can see that PlayWrite is waiting for this element to be attached first before performing all text contents method to be executed. Okay, and what we see, and this is an array, so we need to use an array. And this is an array, so we need to use a different assertion here. So let's replace it with, instead of to equal, we replace it to contain. Run it one more time. And it is again waiting. And this test passed right now successfully. And here is one more example how the locator types of assertion will work with auto weighting. So we expect that success button to have text. And we look for this text. And we know that default timeout for the locator assertion is five seconds. So this assertion should fail right now. So let me comment out this code. And I run only this part. And this should fail in five seconds. Timeout five seconds waiting for expect to have text expected. So expect the string this, but receive string is this because this element was not visible within this timeout. But we can overwrite the timeout for this method. And let's say we use a timeout of 20 seconds. And let's run this one more time. And right now it's fast. So we increase the default timeout from five seconds to 20 seconds. And we know that our button will show up in 15 seconds. So timeout is more than the time that this button should show up. And assertion passed. And let me show you other alternative weights that you can use in Playwright when you're dealing with the commands such as alt text contents that do not have auto weighting feature implemented. So this is the options that you have. So let me create a new test. And I will call it alternative weights. We will use the same locator as our starting point. And we will use these two lines of code as our example of the method that do not have weight, so something like this. So what kind of weights you can use? Example number one is weight for element. A weight page, weight for selector. And you can provide the selector that we want to wait for. And we want to wait for our particular button, right? That's it. So let me run this alternative weight. And you can see that it is patiently waiting for this selector to be available based on our timeout. And the test passed, we got the text and made the assertion. Okay, second example, you can wait for particular response. So what I mean, if we go back to the test application, usually all the information that we have on the web page displayed coming from the back end server and this information coming from the API. The information with interaction of the API located in this networking tab. So if I refresh the page, click refresh, we can see that many things are happening here in the background. So I click on the button and we can see that this Ajax data call is happening. And we see the pending status. So this kind of a simulation of networking requests that we are waiting for. And after 15 seconds, we see the time 15 seconds, we have a successful response and the response status code of three or four. And sometimes we can just wait for the API call to be completed as well. So let's trigger this condition, await page, wait for response. And we need to provide the URL of the response that we are waiting for. Going back here, I click on this request, click on headers. And this is the URL that we are waiting for. I just copy this URL, paste it here. I comment out the previous line. And right now Playwright will wait for this networking request to be successfully completed. And only then we will go to the next step to this line of code. And here we go. We can see that Playwright is waiting right now for this network call. And also this test pass successfully. Okay, what else you can do? Wait for network calls to be completed. And I would mark it as not recommended, but sometimes can be useful. So you can use this type of wait to make sure that all API calls were completed for your application. And it is in completely loaded state. And that way you can be assured that everything that should be loaded for your application is actually loaded. So what we can do is await page dot wait for load state. And you can provide the load state that we are waiting for. For example, network is idle. So Playwright will wait until all the API calls in the networking tab of the browser will be completed. And only then we'll move to the next line. But again, this approach is not recommended because if some of the API calls is stuck, your test will also be stuck at this point. And some of those API calls may not be that really important for the functionality of your application. So be really careful about these types of wait. And I'm running this one more time. And you can see it also works fine. We are in the line number 32. We are waiting for the network to be idle. And after 15 seconds, it worked just fine. Our test passed successfully. And what are other types of waits that you can explore by yourself? Page dot wait for. So you can also wait for a particular event to be triggered. You can wait for a function. You can wait for the request. So I already showed you an example of the certain response. But you can also wait for API request that your browser sent. And you can wait just for the timeout itself. So you can hard code, for example, wait for five seconds. And it's hard coded wait. It's not recommended way, of course. But still, you can use this approach as well. And what is left? Wait for and wait for the particular URL. So this approach can be useful if you navigate to a particular page and you wait for this URL to be available. So this is the alternative waits that you can use in the Playwright. When you're dealing with the commands of the Playwright, they do not have automatic wait implemented. All right, guys. So let's quickly summarize what we did in this lesson. Playwright has automatic waiting mechanism for the certain conditions to be satisfied, such as attach visible, stable, receive events, enable, and editable. And also Playwright has a limited number of the methods that supports this auto-waiting. The list of this method you can find here in the Playwright documentation. The table provides the method name and what kind of conditions this method will automatically wait on the page to be satisfied. The duration of this wait is defined by the timeout settings. If you're interacting with the elements that do not support auto-waiting, for example, all text contents, you can add additional wait to wait for a specific state. Or you can use alternative ways, such as wait for the selector, wait for the response, and a few others that you can choose that works best for you. All right, that's it, guys. And see you in the next lesson.