Element Waiting
Use waitForElement() whenever content appears asynchronously and timing is uncertain.
Why this matters
Section titled “Why this matters”Fixed sleeps (await Bun.sleep(1000)) make tests flaky:
- too short: intermittent failures
- too long: slower runs
Waiting by selector is both faster and more reliable.
Strategy selection
Section titled “Strategy selection”observer
Section titled “observer”Best for pages that inject nodes via JavaScript and trigger DOM mutations.
await view.waitForElement("[data-testid='checkout-button']", { strategy: "observer", timeoutMs: 8000,});observer + observerMode: "shared"
Section titled “observer + observerMode: "shared"”Best when you run many waits in one flow and want to reuse observer infrastructure.
await view.waitForElement("#step-1", { strategy: "observer", observerMode: "shared", sharedObserverTtlMs: 15_000, timeoutMs: 5_000,});
await view.waitForElement("#step-2", { strategy: "observer", observerMode: "shared", sharedObserverTtlMs: 20_000, timeoutMs: 5_000,});If the second wait requests a larger TTL than remaining idle time, the shared observer TTL is extended.
Best as a simple fallback and when you want explicit interval control.
await view.waitForElement(".toast-success", { strategy: "poll", intervalMs: 100, timeoutMs: 4000,});Cancellation with AbortSignal
Section titled “Cancellation with AbortSignal”const controller = new AbortController();const timeout = setTimeout(() => controller.abort(), 3000);
try { const found = await view.waitForElement(".slow-widget", { strategy: "poll", intervalMs: 150, timeoutMs: 10000, signal: controller.signal, });
if (!found) { throw new Error("Widget never appeared"); }} finally { clearTimeout(timeout);}Recommended pattern
Section titled “Recommended pattern”await view.navigate("https://example.com/dashboard");await view.waitForDocumentReady({ state: "complete", timeoutMs: 15000 });
await view.waitForElement("main", { strategy: "observer", timeoutMs: 8000 });await view.waitForElement("button[data-action='refresh']", { strategy: "observer", observerMode: "shared", sharedObserverTtlMs: 10000, timeoutMs: 6000,});This combines document readiness with element readiness to avoid racing against hydration.
Troubleshooting
Section titled “Troubleshooting”Wait times out even though the element exists
Section titled “Wait times out even though the element exists”- Verify selector correctness in DevTools.
- Confirm you are waiting in the correct frame/context.
- Increase
timeoutMsfor slower environments.
Waits become expensive in long scripts
Section titled “Waits become expensive in long scripts”- Use shared observer mode for repeated waits.
- Scope selectors to specific containers when possible.
Abort behavior seems inconsistent
Section titled “Abort behavior seems inconsistent”- Pass a fresh
AbortControllerper wait. - Use
pollstrategy if you need straightforward interval-based cancellation behavior.