Skip to content

Element Waiting

Use waitForElement() whenever content appears asynchronously and timing is uncertain.

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.

Best for pages that inject nodes via JavaScript and trigger DOM mutations.

await view.waitForElement("[data-testid='checkout-button']", {
strategy: "observer",
timeoutMs: 8000,
});

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,
});
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);
}
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.

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 timeoutMs for slower environments.
  • Use shared observer mode for repeated waits.
  • Scope selectors to specific containers when possible.
  • Pass a fresh AbortController per wait.
  • Use poll strategy if you need straightforward interval-based cancellation behavior.