Understanding the use of 'await' with Playwright
Akash Chaudhary
?? Full Stack QA | "I'm the one who tests" | Architecting Excellence in Software Quality
The Restaurant
You walked in to a restaurant, super hungry. You are asked to wait in the queue for the table. I know, irritating. What else we can do because the restaurant makes best pancakes in the town.
The Wait
First you have wait to get a table and then you wait for the waiter to attend you. Painful but this is a given.
When finally the waiter attends you, now you have to wait again to get your food served(after you give the order of course).
The Productive Use of Wait
What you might do during this time
What you are not supposed to do
Poke the waiter again and again and again. Probably, not the right thing to annoy the busy guy.
The Promise
Now let's equate this scenario with programming. The first approach is similar to asynchronous programming. You are using your time while waiting for the other task to complete. The second approach is similar to synchronous programming - you are holding everything until this task completes(poking the waiter like he has nothing else to do).
When the waiter has assured you that he will fetch a menu for you, you will wait for this promise to fulfill. If waiter finds a menu or if the waiter fails to find one(because they are all occupied). The outcome of this promise will decide what will you order.
The promise can be fulfilled or rejected.
I hope it clears the very basic idea of asynchronous and synchronous programming. Let's now comeback to Playwright.
The await Keyword in Playwright
When you call a function like page.goto(), you ask Playwright to open a page. You are supposed to await here because if this promise is not fulfilled, your next step(locating elements on this page) will not work.
This (and similar such steps) require the use of await keyword
await page.goto("/services/menu");
await page.getByTestId("veg-menu").click();
//further code
So in a nutshell:
领英推荐
When Playwright is performing tasks that depend on remote resources, elements, or APIs, it relies on asynchronous operations that involve promises. You need to use await keyword in such cases.
When Not to Use await Keyword
Now imagine the scenario when the waiter has given you the menu. You can read, decide on your own pace and you do not depend on waiter to check the menu. You don't need to wait for anything - start checking the menu right away.
Let's equate this with TS code:
await page.goto("/services/menu");
await page.getByTestId("veg-menu").click();
const vegetablesCurryAmount = await page.getByTestId("veg-curry-amount").textContent()
//no use of await
expect(parseFloat(vegetablesCurryAmount)).not.toBeGreaterThan(250);
When you expecting(asserting) on a resource that is already fetched and does not require to load again and again, you don't need to use await. Simply, synchronous assertion. There are no asynchronous operations here, so using await is unnecessary.
These are called Non-retrying assertions in Playwright.
Look at this example now:
//this time no use of await here
const vegetablesCurryAmountLocator = page.getByTestId("veg-curry-amount")
//but we have to use await (remember the text is on remote element and we have not fetched it yet)
await expect(vegetablesCurryAmountLocator).toContainText(expectedAmount)
These are called Auto-retrying assertions in Playwright. Playwright will retry until the assertion passes or the assertion timeout is reached.
Best Practices
Whenever you see this warning, check the code and fix the await keyword. Take the advantage of IDE and also learn side by side with it.
Example of an async function in a page object
async selectBookCategory(categoryName: string) {
return await this.categoryListLocator
.filter({ hasText: categoryName })
.click();
}
Takeaway
The key takeaway is to understand where await is necessary and where it isn’t. Misusing it can lead to inefficiencies or unnecessary warnings in your code. By correctly leveraging asynchronous programming and using await only where required, you can write clean, efficient, and performant scripts in Playwright or any other async-enabled environment.
By correctly leveraging asynchronous programming and using await only where required, you can write clean, efficient, and performant scripts in Playwright or any other async-enabled environment.
Software QA Engineer | Tester | Manual & Automation Testing | Playwright | Postman (Certified : Software Quality Assurance | Web Testing | Software Tester)
2 个月Very Informative ??
Software Development Engineer in Testing (SDET) @NTT DATA | Cypress, JavaScript TypeScript | Selenium WebDriver, Java C#| API Testing | Cucumber Specflow | AI/ML Testing | Appium Mobile Automation with WebDriver.Io
2 个月Useful tips