Skip to content

Add waitForURL docs pages #2025

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ Frame represents a single frame in a browser window. It can be a top-level frame
| [waitForNavigation([options])](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/frame/waitfornavigation/) | Waits for the given navigation lifecycle event to occur and returns the main resource response. |
| [waitForSelector(selector[, options])](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/frame/waitforselector/) | Returns when element specified by selector satisfies `state` option. |
| [waitForTimeout(timeout)](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/frame/waitfortimeout) | Waits for the given `timeout` in milliseconds. |
| [waitForURL(url[, options])](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/frame/waitforurl/) | Waits for the frame to navigate to the specified URL. |
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ Waits for the given navigation lifecycle event to occur and returns the main res

<TableWithNestedRows>

| Parameter | Type | Default | Description |
| ----------------- | ------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| options | object | `null` | |
| options.timeout | number | `30000` | Maximum time in milliseconds. Pass `0` to disable the timeout. Default is overridden by the `setDefaultTimeout` option on [BrowserContext](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/browsercontext/) or [Page](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/page/). |
| options.waitUntil | string | `load` | When to consider operation to have succeeded. See [Events](#events) for more details. |
| Parameter | Type | Default | Description |
| ----------------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| options | object | `null` | |
| options.timeout | number | `30000` | Maximum time in milliseconds. Pass `0` to disable the timeout. Default is overridden by the `setDefaultTimeout` option on [BrowserContext](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/browsercontext/) or [Page](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/page/). |
| options.url | string\|RegExp | `null` | URL or URL pattern to match the navigation URL against. Useful when frame navigation performs multiple redirects and you need to wait until a final destination within the frame is reached. |
| options.waitUntil | string | `load` | When to consider operation to have succeeded. See [Events](#events) for more details. |

</TableWithNestedRows>

### When to use the url option

Use `options.url` when frame navigation passes through several intermediate pages (e.g., third‑party authentication or consent flows) before settling on a final URL. Matching the final URL or a regex pattern helps you reliably wait for the intended destination inside the frame. However, opt to work with [waitForURL](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/frame/waitforurl) instead since it mitigates the risk of race conditions better than `waitForNavigation`.

### Events

{{< admonition type="caution" >}}
Expand All @@ -36,3 +41,54 @@ Events can be either:
| Type | Description |
| --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Promise<null \| [Response](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/response/)> | The `Response` instance associated with the frame. Else, it returns `null` |

### Examples

<!-- md-k6:skip -->

```javascript
import { browser } from 'k6/browser';

export const options = {
scenarios: {
browser: {
executor: 'shared-iterations',
options: {
browser: {
type: 'chromium',
},
},
},
},
};

export default async function () {
const page = await browser.newPage();

try {
await page.setContent(`
<iframe src="https://quickpizza.grafana.com/test.k6.io/" width="50%" height="50%"></iframe>
`);

// Retreive the frame of the iframe
const iframeElement = await page.$('iframe');
const frame = await iframeElement.contentFrame();

// Wait for navigation to a specific URL
await Promise.all([
frame.click('a[href="/my_messages.php"]'),
frame.waitForNavigation({ url: 'https://quickpizza.grafana.com/my_messages.php' }),
]);

await frame.goto('https://quickpizza.grafana.com/test.k6.io/');

// Wait for navigation using URL pattern with RegExp
await Promise.all([
frame.click('a[href="/browser.php"]'),
frame.waitForNavigation({ url: /\/browser\.php$/ }),
]);
} finally {
await page.close();
}
}
```
146 changes: 146 additions & 0 deletions docs/sources/k6/next/javascript-api/k6-browser/frame/waitforurl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
title: 'waitForURL(url[, options])'
description: 'Browser module: frame.waitForURL(url[, options]) method'
---

# waitForURL(url[, options])

Waits for the frame to navigate to the specified URL. This method is useful for ensuring that navigation within a specific frame (such as an iframe) to a particular URL has completed before proceeding with the test. This is especially useful if there are multiple redirects before hitting the end destination.

<TableWithNestedRows>

| Parameter | Type | Default | Description |
| ----------------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| url | string\|RegExp | - | Required. URL or URL pattern to match against. The method will wait until the frame navigates to a URL that matches this parameter. |
| options | object | `null` | |
| options.timeout | number | `30000` | Maximum time in milliseconds. Pass `0` to disable the timeout. Default is overridden by the `setDefaultTimeout` option on [BrowserContext](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/browsercontext/) or [Page](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/page/). |
| options.waitUntil | string | `load` | When to consider operation to have succeeded. See [Events](#events) for more details. |

</TableWithNestedRows>

### Events

{{< admonition type="caution" >}}

`networkidle` is DISCOURAGED. Don't use this method for testing especially with chatty websites where the event may never fire, rely on web assertions to assess readiness instead.

{{< /admonition >}}

Events can be either:

- `'domcontentloaded'` - consider operation to be finished when the `DOMContentLoaded` event is fired.
- `'load'` - consider operation to be finished when the `load` event is fired.
- `'networkidle'` - Consider operation to be finished when there are no network connections for at least `500` ms.

### Returns

| Type | Description |
| ------- | ------------------------------------------------------------------------------------------------------------------------ |
| Promise | A Promise that resolves when the frame has navigated to the specified URL and the specified load state has been reached. |

### Examples

<!-- md-k6:skip -->

```javascript
import { browser } from 'k6/browser';

export const options = {
scenarios: {
browser: {
executor: 'shared-iterations',
options: {
browser: {
type: 'chromium',
},
},
},
},
};

export default async function () {
const page = await browser.newPage();

try {
await page.setContent(`
<iframe src="https://quickpizza.grafana.com/test.k6.io/" width="50%" height="50%"></iframe>
`);

const iframeElement = await page.$('iframe');
const iframeContent = await iframeElement.contentFrame();

// Wait for navigation to a specific URL
await Promise.all([
iframeContent.click('a[href="/my_messages.php"]'),
iframeContent.waitForURL('https://quickpizza.grafana.com/my_messages.php'),
]);

await iframeContent.goto('https://quickpizza.grafana.com/test.k6.io/');

// Wait for navigation using URL pattern with RegExp
await Promise.all([
iframeContent.click('a[href="/browser.php"]'),
iframeContent.waitForURL(/\/browser\.php$/),
]);
} finally {
await page.close();
}
}
```

### Valid usage patterns for waitForURL

Use one of the following patterns to coordinate the action that triggers navigation with waiting for the final URL.

<!-- eslint-skip -->

```js
await Promise.all([
frame.waitForURL('https://quickpizza.grafana.com/my_messages.php'),
frame.locator('a[href="/my_messages.php"]').click(),
]);
```

or

<!-- eslint-skip -->

```js
const navPromise = frame.waitForURL('https://quickpizza.grafana.com/my_messages.php');
await frame.locator('a[href="/my_messages.php"]').click();
await navPromise;
```

Unlike [waitForNavigation](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/page/waitfornavigation), `waitForURL` will first check whether it is already on the page with the given URL before proceeding to wait. If it is already there and the `waitUntil` condition has also been met, it will return straight away. This means that it is safe to do this:

<!-- eslint-skip -->

```js
await frame.locator('a[href="/my_messages.php"]').click();
await frame.waitForURL('https://quickpizza.grafana.com/my_messages.php');
```

### Best practices

1. **Verify frame existence**: Frames can be created, destroyed, or replaced during page navigation. Always verify frame existence before calling `waitForURL()`.

2. **Use appropriate selectors**: Use frame selectors that are stable and unique.

3. **Handle cross-origin scenarios**: Be aware of limitations when working with cross-origin iframes.

4. **Combine with content verification**: After URL change, verify that the expected content is present.

5. **Consider frame timing**: Frame navigation may happen after page navigation, so allow appropriate time.

### Common use cases

- **Payment processing**: Waiting for payment iframe redirects
- **Social media embeds**: Handling navigation in embedded social content
- **OAuth flows**: Managing authentication within iframes
- **Multi-frame applications**: Coordinating navigation across multiple frames
- **Embedded widgets**: Testing third-party widget navigation

### Related

- [frame.waitForNavigation()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/frame/waitfornavigation/) - Wait for frame navigation events
- [frame.waitForLoadState()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/frame/waitforloadstate/) - Wait for load states
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,5 @@ Page provides methods to interact with a single tab in a running web browser. A
| [waitForNavigation([options])](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/page/waitfornavigation/) | Waits for the given navigation lifecycle event to occur and returns the main resource response. |
| [waitForSelector(selector[, options])](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/page/waitforselector/) | Returns when element specified by selector satisfies `state` option. |
| [waitForTimeout(timeout)](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/page/waitfortimeout) | Waits for the given `timeout` in milliseconds. |
| [waitForURL(url[, options])](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/page/waitforurl/) | Waits for the page to navigate to the specified URL. |
| [workers()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/page/workers) | Returns an array of the dedicated [WebWorkers](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/worker) associated with the page. |
Loading