TestifyStack | Email, SMS, OTP and Webhooks Testing Stack for QA & Dev

Do you enjoy this platform? ❤️ Buy us a coffee

Playwright Async/Await — Easy Explained

Problem: Asynchronous (No waiting): Things Happen Out of Order 🚗

When writing JavaScript, some actions take time to complete — like loading a file, fetching data, or waiting.
These are asynchronous tasks. If we don’t manage them correctly, steps can happen out of order.

Let’s use a super simple example to understand and fix this.

You want to:

  1. 🔑 Start a car
  2. 🚙 Move the car
  3. 🛑 Stop the car
drawing

But starting the car takes 2 seconds. If we write normal code like this:

function startCar() {
  setTimeout(() => {
    console.log("Car started");
  }, 2000);
}

function moveCar() {
  console.log("Car is moving");
}

function stopCar() {
  console.log("Car stopped");
}

startCar();
moveCar();
stopCar();

Output (WRONG ORDER):

Car is moving
Car stopped
Car started

Everything happens too early! The car moved and stopped before it even started! 😲

Fix 1: Using Callback

function startCar(callback) {
  setTimeout(() => {
    console.log("Car started");
    callback();
  }, 2000);
}

function moveCar(callback) {
  console.log("Car is moving");
  callback();
}

function stopCar() {
  console.log("Car stopped");
}

// Run steps in correct order using callbacks
startCar(() => {
  moveCar(() => {
    stopCar();
  });
});

Output:

Car started
Car is moving
Car stopped

Fix 2: Using Promise

function startCar() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log("Car started");
      resolve();
    }, 2000);
  });
}

function moveCar() {
  return new Promise((resolve) => {
    console.log("Car is moving");
    resolve();
  });
}

function stopCar() {
  console.log("Car stopped");
}

startCar()
  .then(() => moveCar())
  .then(() => stopCar());

Fix 3: Using CalAsync/Await (Cleanest way)

function startCar() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log("Car started");
      resolve();
    }, 2000);
  });
}

function moveCar() {
  return new Promise((resolve) => {
    console.log("Car is moving");
    resolve();
  });
}

function stopCar() {
  console.log("Car stopped");
}

async function driveCar() {
  await startCar();
  await moveCar();
  stopCar();
}

driveCar();

Concepts Refresher

Concept What It Means
Callback “When you're done, call this function.”
Promise “I promise to tell you when I’m done.”
Async/Await “Wait for this step to finish.”

Playwright Test Example: Async/Await in Action

Here’s a basic Playwright test demonstrating async/await to control browser steps:


import { test, expect } from "@playwright/test";

test.describe("Auth Tests", () => {

  test("should be able to login with valid credentials", async ({ page }) => {
    // Navigate to login page
    await page.goto("https://practice.expandtesting.com/login");

    // Fill username and password
    await page.locator("#username").fill("practice");
    await page.locator("#password").fill("SuperSecretPassword!");

    // Click Login button
    await page.getByRole("button", { name: "Login" }).click();

    // Wait for URL to change after login
    await page.waitForURL("https://practice.expandtesting.com/secure");

    // Verify success message is visible and contains expected text
    await expect(page.locator("div#flash-message")).toHaveText(/You logged into a secure area!/);
  });

});