Lesson 7 of 9

Lesson 07 — Async / await for testers

Title: Promises, sequencing steps, and simulated APIs

Description: Automation is inherently asynchronous — browsers and networks resolve later. Learn how TypeScript surfaces Promise types.

Why it matters for QA: Playwright APIs return promises; mishandling (forget await) yields flaky races TypeScript sometimes warns about.


1. Async functions return promises

typescripttypescript
async function getData(): Promise<string> {
  return "data loaded";
}

async function run(): Promise<void> {
  const result = await getData();
  console.log(result);
}

void run();

2. Simulated latency API

typescripttypescript
const delay = (ms: number): Promise<void> =>
  new Promise((resolve) => {
    setTimeout(resolve, ms);
  });

const fetchUser = async (id: number): Promise<{ id: number; name: string }> => {
  await delay(50);
  return { id, name: `User ${id}` };
};

async function demo(): Promise<void> {
  const user = await fetchUser(7);
  console.log(user);
}

void demo();

3. Errors bubble — plan try/catch

typescripttypescript
async function fragile(): Promise<void> {
  try {
    await fetchUser(-1);
  } catch (error) {
    console.error("Recovery path", error);
  }
}

4. Sequential vs concurrent

typescripttypescript
async function sequential(ids: number[]): Promise<void> {
  for (const id of ids) {
    const user = await fetchUser(id);
    console.log(user.name);
  }
}

async function concurrent(ids: number[]): Promise<void> {
  const users = await Promise.all(ids.map((id) => fetchUser(id)));
  console.log(users.map((user) => user.name).join(", "));
}

QA note: hitting real backends concurrently may trip rate limits — choose style on purpose.