Real World QA & DOM
Real World QA & DOM: querySelector — Selecting Elements in the DOM In real-world automation suites (Playwright/Cypress), waiting for asynchronous API calls and page loads is crit
querySelector — Selecting Elements in the DOM
In real-world automation suites (Playwright/Cypress), waiting for asynchronous API calls and page loads is critical. When writing `await page.click('button')`, we pause execution until the underlying Promise resolves. Think of it as ordering in a restaurant: writing `Thread.sleep(5000)` is telling the waiter "my food will probably take 5 minutes" and then blindly reaching for the table at exactly the 5-minute mark — too early and it isn't there, too late and you wasted the wait. `await` waits for the MOMENT the plate lands: not a second early, not a second late. So if both of them wait, why is a fixed delay so much worse? Because a fixed delay produces two failures at once: it is TOO SHORT when the machine is slow (a flaky test) and NEEDLESSLY long when it is fast (multiply that across a 200-test suite and it costs you half an hour). The rule that tells you to prefer `WebDriverWait`/explicit waits over `Thread.sleep()` in Java holds here too — with one difference: in JavaScript waiting is baked into the language, so forgetting `await` raises no error at all; your code simply keeps working with the Promise object itself and the assertion passes silently. For QA, most flaky-test complaints live exactly in the gap between those two lines.
Asynchronous Test with Playwright
import { test, expect } from '@playwright/test'; test('Async data loading test', async ({ page }) => { // 1. Navigate to website (returns a Promise, await resolves it) await page.goto('https://example.com'); // 2. Click the button (Playwright auto-waits until element is ready) await page.click('#load-data-btn'); // 3. Wait until API data appears on screen const welcomeText = page.locator('.welcome-msg'); await expect(welcomeText).toBeVisible({ timeout: 5000 }); });
Micro Lab: JavaScript QA coding practice
Replace the TODO line with the critical line from the expected solution. This is not a real runtime; the goal is to reinforce writing the correct structure in a controlled way.
Why Would This Test Fail Randomly Without await?
await page.goto(...) blocks…
await page.goto(...) makes JavaScript NOT MOVE to the next line until the page is FULLY loaded and the Promise RESOLVES — without await, the code would continue immediately, possibly before the page even opened.
await page.click(...) waits FIRST…
await page.click(...) waits FIRST for the element's actionability check (visible/enabled/stable), THEN clicks — this wait happens AUTOMATICALLY inside Playwright, you never write a separate "sleep".
const welcomeText = page.locator(...) runs…
const welcomeText = page.locator(...) does NOT run any DOM query YET — locators are "lazy", the actual search is DEFERRED until await expect(...) is called.
await expect(welcomeText).toBeVisible({ timeout: 5000 })…