# How to Wait for Specific Page Conditions in ego-lite: Load States, URLs, and Element Visibility

> Master ego-lite waits to pause script execution for load states, URLs, and element visibility. Enhance your Playwright-style tests with efficient condition handling.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: how-to-guide
- Published: 2026-08-21

---

**Ego-lite provides Playwright-style wait helpers in [`driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/waits.ts) that pause script execution until specific page conditions—such as load states, URL patterns, network activity, or element visibility—are met.**

Ego-lite is a browser automation framework that abstracts Chrome DevTools Protocol (CDP) complexity into high-level synchronization primitives. Understanding how to wait for specific page conditions is essential for writing reliable automation scripts that avoid race conditions and ensure actions execute only when the page is actually ready.

## Waiting for Page Load States

The `waitForLoadState()` function in [`package/ego-browser/src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/waits.ts) serves as the primary entry point for page lifecycle synchronization. It supports three distinct load milestones:

- **`load`** – `document.readyState` equals `complete`
- **`domcontentloaded`** – `document.readyState` is `interactive` or `complete`
- **`networkidle`** – No network requests have been in-flight for a configurable idle period

### The waitForLoadState Implementation

According to the source code, `waitForLoadState()` normalizes its arguments at lines 55-58, accepting either a string state name or an options object. The implementation bifurcates based on the requested state:

- For `"networkidle"`, it delegates to `waitForNetworkIdle()` (lines 62-64)
- For `"load"` or `"domcontentloaded"`, it invokes `waitForDocumentLoad()` (lines 66-68)

The `waitForDocumentLoad()` helper (located in [`driver/load.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/load.ts)) polls `document.readyState` every few milliseconds (lines 25-27) until the required state appears or the global timeout expires.

### Network Idle Detection

When requesting `networkidle`, ego-lite enables the Network CDP domain and monitors request activity. The system considers the page idle when no new network requests have started or remained in-flight for the specified duration, preventing premature interactions with pages that continue loading resources.

```javascript
// Wait for the page to fully load and all network activity to cease
await waitForLoadState('networkidle', { timeout: 15000 });

// Wait only for DOM readiness before proceeding
await waitForLoadState('domcontentloaded');

```

## Waiting for URL Navigation

The `waitForURL()` function (lines 84-118 in [`driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/waits.ts)) repeatedly evaluates `location.href` via `Runtime.evaluate` and validates it against flexible matchers. It accepts strings, globs, regular expressions, or predicate functions through the `urlMatches` helper (lines 14-30).

If the caller specifies a `waitUntil` option, `waitForURL()` automatically chains into `waitForLoadState()` after the URL matches, ensuring the document reaches the desired ready state before returning control to the script.

```javascript
// Wait for checkout URL pattern then ensure document is complete
await waitForURL('**/checkout', { waitUntil: 'load' });

// Wait with regex pattern and custom timeout
await waitForURL(/\/dashboard\/\d+/, { timeout: 10000 });

```

## Waiting for Network Requests and Responses

For scenarios requiring synchronization with specific HTTP traffic, ego-lite exposes `waitForRequest()` and `waitForResponse()`. Both functions share the private `waitForNetworkMatch()` implementation (lines 50-77 in [`driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/waits.ts)).

The workflow involves:

1. **Enabling network monitoring** via `acquireNetworkEvents()` (lines 49-82), which activates the Network CDP domain only when needed
2. **Listening for CDP events** through `waitForBrowserEvent()` until a request or response matches the supplied predicate (`networkMatches`, lines 22-38)

```javascript
// Wait for a specific API request to initiate
await waitForRequest(url => url.includes('/api/cart'));

// Wait for the response to complete with specific status
const response = await waitForResponse(req => req.url.includes('/api/user'));

```

## Waiting for Elements and Visibility

The `waitForSelector()` function (lines 85-112 in [`driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/waits.ts)) provides robust element detection with optional visibility guarantees. It combines handle-based resolution with browser-side JavaScript evaluation.

The implementation follows this sequence:

1. **Resolve the selector** using `resolveHandle()` (line 103), which maps CSS selectors, XPath expressions, or reference handles (`@ref`, `loc=`) to remote object handles
2. **Handle transient elements** by retrying every 300ms (`state.sleep(300)`) if resolution fails
3. **Check visibility** via `Runtime.callFunctionOn` executing the `visibilityFn` (line 99) if the `state: 'visible'` option is specified
4. **Cleanup** by calling `releaseHandle()` (line 127) to prevent memory leaks in the CDP session

```javascript
// Wait for element to exist in DOM
await waitForSelector('#submit-button');

// Wait for element to exist AND be visible
if (await waitForSelector('#confirm', { state: 'visible' })) {
  await click('#confirm');
}

// Wait with custom timeout and visibility requirement
await waitForSelector('.modal-content', { 
  state: 'visible', 
  timeout: 5000 
});

```

## Summary

- **Load state synchronization** uses `waitForLoadState()` in [`driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/waits.ts) to monitor `document.readyState` or network idle conditions through [`driver/load.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/load.ts) and network CDP domains.
- **URL-based waiting** employs `waitForURL()` with flexible matchers and optional subsequent load state validation.
- **Network traffic waiting** leverages `waitForRequest()` and `waitForResponse()` via the shared `waitForNetworkMatch()` helper that temporarily enables network event monitoring.
- **Element detection** relies on `waitForSelector()` which uses handle resolution (`resolveHandle`/`releaseHandle`) from [`element-ops.ts`](https://github.com/citrolabs/ego-lite/blob/main/element-ops.ts) and browser-side visibility checks to confirm elements are ready for interaction.
- All wait operations respect the global timeout configuration from [`state.ts`](https://github.com/citrolabs/ego-lite/blob/main/state.ts) and use efficient polling intervals to balance responsiveness against CPU usage.

## Frequently Asked Questions

### What is the difference between "load" and "networkidle" in ego-lite?

The `"load"` state triggers when `document.readyState` becomes `complete`, indicating the HTML document and its immediate resources have finished parsing. The `"networkidle"` state requires that no network requests have been initiated or remained in-flight for a configurable idle period, ensuring that asynchronous scripts and dynamic content have finished loading.

### How does ego-lite check element visibility during waits?

When `waitForSelector()` receives the `state: 'visible'` option, it executes a browser-side visibility function via `Runtime.callFunctionOn` (defined at line 99 in [`waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/waits.ts)). This function checks computed styles, bounding rectangles, and DOM properties to determine if the element is actually displayed to users before resolving the promise.

### Can I wait for specific HTTP status codes or request methods?

Yes, the `waitForRequest()` and `waitForResponse()` functions accept predicate functions through the `networkMatches` helper (lines 22-38). You can inspect the request object for `method`, `url`, `headers`, or the response for `status`, providing fine-grained control over which network events unblock your automation script.

### What happens if a wait operation times out?

All wait functions in [`driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/waits.ts) reference the global `state` singleton from [`state.ts`](https://github.com/citrolabs/ego-lite/blob/main/state.ts) for default timeout values. When the timeout expires before the condition is met, the promise rejects with a timeout error, allowing your script to catch the exception and implement fallback logic or retries.