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
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
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
async function fragile(): Promise<void> {
try {
await fetchUser(-1);
} catch (error) {
console.error("Recovery path", error);
}
}
4. Sequential vs concurrent
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.