Navigations
Introduction
CSTesting can navigate to URLs and work with navigations caused by page interactions (e.g. clicking a link or submitting a form). This page describes basic navigation, when the page is considered loaded, and how to wait for a specific URL after an action.
Basic navigation
The main way to open a URL is browser.gotoUrl(url):
browser.gotoUrl("https://example.com");
This loads the page. With the CDP implementation, navigation completes when the browser has loaded the document. For more control, you can call waitForLoad() or waitForLoad(timeoutMs) after gotoUrl to wait until document.readyState is complete (all resources such as stylesheets, scripts, and images have loaded, and the load event has fired).
browser.gotoUrl("https://example.com");
browser.waitForLoad(10_000);
If the page does a client-side redirect before load, gotoUrl (and any following waitForLoad) applies to the final loaded page.
Other navigation commands:
| Method | Description |
|---|---|
browser.back() | Navigate back in history. |
browser.forward() | Navigate forward in history. |
browser.refresh() | Reload the current page. |
browser.url() | Return the current page URL. |
When is the page loaded?
Modern pages often do more after the load event: they fetch data lazily, fill in the UI, or load extra scripts and styles. There is no single definition of "fully loaded"; it depends on the page and framework.
In CSTesting you can interact with the page at any time. Actions (click, type, etc.) use auto-waiting: CSTesting waits for the target element to be actionable (visible, enabled, etc.) before performing the action. So you usually don't need to wait for "everything" to load—only for the elements you use.
Example – navigate and click:
browser.gotoUrl("https://example.com");
browser.locator("//*[contains(.,'Example Domain')]").first().click();
The click auto-waits for the element to become visible and pass actionability checks, then clicks. You can think of CSTesting as a fast user: as soon as the element is ready, it acts. In many cases you don't need to worry about whether all resources have finished loading.
If you prefer to wait for the document first, call waitForLoad() or waitForLoad(timeoutMs) after gotoUrl:
browser.gotoUrl("https://example.com");
browser.waitForLoad(5_000);
browser.locator("h1").click();
Hydration
Sometimes you'll see a case where an action seems to do nothing—for example you click a button and nothing happens, or you type into an input and the text disappears. A common cause is poor hydration (e.g. in SPAs).
With hydration, the server first sends a static version of the page; then the dynamic part loads and the page becomes "live." If CSTesting interacts as soon as the button is visible but before the app has attached its listeners, the click may have no effect or the input may be reset when the framework takes over.
To check for this, you can slow down the network (e.g. Chrome DevTools → Network → "Slow 3G"), reload the page, and try interacting as soon as the element appears. If clicks are ignored or text is cleared, the fix is on the app side: disable interactive controls until after hydration, when the page is fully functional.
Waiting for navigation
Clicking a link or submitting a form can trigger a navigation to a new URL. In those cases it's a good idea to wait for the new URL before continuing the test.
Use waitForURL(urlOrPattern, timeoutMs) after the action that triggers the navigation. The URL can be an exact string, a substring (match when the current URL contains it), or a pattern with * as a wildcard.
browser.locator("//*[contains(.,'Click me')]").first().click();
browser.waitForURL("**/login", 10_000);
browser.assertThat().hasTitle("Login");
Examples:
browser.waitForURL("https://example.com/dashboard", 5_000); // exact or contains
browser.waitForURL("**/dashboard", 5_000); // * matches any segment
browser.waitForURL("**/users/*/profile", 5_000); // multiple wildcards
If the URL doesn't match within timeoutMs, waitForURL throws. Omit timeoutMs (or pass null) to use the default timeout (e.g. 30 seconds, depending on implementation).
Navigation and loading (overview)
Conceptually, showing a new document involves:
- Navigation – The URL changes (e.g. by
gotoUrlor by clicking a link). The browser resolves the URL and may follow redirects. - Loading – The response is received, the document is parsed, scripts run, and the load event fires when the document and its main resources are loaded.
CSTesting does not expose fine-grained navigation events (e.g. "navigation committed" or "DOMContentLoaded"). You can:
- Use
gotoUrl(url)to start a navigation. - Use
waitForLoad()/waitForLoad(timeoutMs)to wait untildocument.readyState === 'complete'(and typically theloadevent). - Use
waitForURL(urlOrPattern, timeoutMs)to wait until the current URL matches after an action (e.g. after a click that triggers navigation). - Use
url()to read the current URL at any time.
Optional: wait for network idle
If you need to wait until the page has loaded and there are no pending network requests for a short period, you can use waitForNetworkLoad(timeoutMs) (when supported by the backend). This is stricter than waitForLoad and may not be necessary for most tests; prefer waitForLoad and auto-waiting on elements.
Summary
| Topic | CSTesting |
|---|---|
| Open URL | browser.gotoUrl(url) |
| Wait for document ready | browser.waitForLoad() or browser.waitForLoad(timeoutMs) |
| Back / forward / refresh | browser.back(), browser.forward(), browser.refresh() |
| Current URL | browser.url() |
| Wait for URL after action | browser.waitForURL(urlOrPattern, timeoutMs) (supports * wildcard) |
| When to interact | Anytime; actions auto-wait for elements. Use waitForLoad if you want document-ready first. |
| Hydration issues | Disable controls until the app is hydrated; use slow network to reproduce. |