Understanding the use of 'await' with Playwright

Understanding the use of 'await' with Playwright

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

  • Conversations with your family or friends while waiting initially?
  • Chatting on smartphone or reading a book
  • Nothing, just being presence in the moment and checking around

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

  • When you are using IDE like VS Code, you will see VS code suggesting you the right use of await. Look at this screenshot from VS Code.

The 3 dots under await are notifying the redundant use

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.

  • await can only be used with async functions. it pauses the execution of the current async function until the promise resolves, but it does not block the entire program.

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.

Kashaf Ud Duja

Software QA Engineer | Tester | Manual & Automation Testing | Playwright | Postman (Certified : Software Quality Assurance | Web Testing | Software Tester)

2 个月

Very Informative ??

Ranajit Jyoti

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

要查看或添加评论,请登录

Akash Chaudhary的更多文章

社区洞察

其他会员也浏览了