|
| 1 | +--- |
| 2 | +title: 'waitForURL(url[, options])' |
| 3 | +description: 'Browser module: frame.waitForURL(url[, options]) method' |
| 4 | +--- |
| 5 | + |
| 6 | +# waitForURL(url[, options]) |
| 7 | + |
| 8 | +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. |
| 9 | + |
| 10 | +<TableWithNestedRows> |
| 11 | + |
| 12 | +| Parameter | Type | Default | Description | |
| 13 | +| ----------------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 14 | +| 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. | |
| 15 | +| options | object | `null` | | |
| 16 | +| 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/). | |
| 17 | +| options.waitUntil | string | `load` | When to consider operation to have succeeded. See [Events](#events) for more details. | |
| 18 | + |
| 19 | +</TableWithNestedRows> |
| 20 | + |
| 21 | +### Events |
| 22 | + |
| 23 | +{{< admonition type="caution" >}} |
| 24 | + |
| 25 | +`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. |
| 26 | + |
| 27 | +{{< /admonition >}} |
| 28 | + |
| 29 | +Events can be either: |
| 30 | + |
| 31 | +- `'domcontentloaded'` - consider operation to be finished when the `DOMContentLoaded` event is fired. |
| 32 | +- `'load'` - consider operation to be finished when the `load` event is fired. |
| 33 | +- `'networkidle'` - Consider operation to be finished when there are no network connections for at least `500` ms. |
| 34 | + |
| 35 | +### Returns |
| 36 | + |
| 37 | +| Type | Description | |
| 38 | +| ------- | ------------------------------------------------------------------------------------------------------------------------ | |
| 39 | +| Promise | A Promise that resolves when the frame has navigated to the specified URL and the specified load state has been reached. | |
| 40 | + |
| 41 | +### Examples |
| 42 | + |
| 43 | +{{< code >}} |
| 44 | + |
| 45 | +```javascript |
| 46 | +import { browser } from 'k6/browser'; |
| 47 | + |
| 48 | +export const options = { |
| 49 | + scenarios: { |
| 50 | + browser: { |
| 51 | + executor: 'shared-iterations', |
| 52 | + options: { |
| 53 | + browser: { |
| 54 | + type: 'chromium', |
| 55 | + }, |
| 56 | + }, |
| 57 | + }, |
| 58 | + }, |
| 59 | +}; |
| 60 | + |
| 61 | +export default async function () { |
| 62 | + const page = await browser.newPage(); |
| 63 | + |
| 64 | + try { |
| 65 | + await page.setContent(` |
| 66 | + <iframe src="https://quickpizza.grafana.com/test.k6.io/" width="50%" height="50%"></iframe> |
| 67 | + `); |
| 68 | + |
| 69 | + const iframeElement = await page.$('iframe'); |
| 70 | + const iframeContent = await iframeElement.contentFrame(); |
| 71 | + |
| 72 | + // Wait for navigation to a specific URL |
| 73 | + await Promise.all([ |
| 74 | + iframeContent.click('a[href="/my_messages.php"]'), |
| 75 | + iframeContent.waitForURL('https://quickpizza.grafana.com/my_messages.php'), |
| 76 | + ]); |
| 77 | + |
| 78 | + await iframeContent.goto('https://quickpizza.grafana.com/test.k6.io/'); |
| 79 | + |
| 80 | + // Wait for navigation using URL pattern with RegExp |
| 81 | + await Promise.all([ |
| 82 | + iframeContent.click('a[href="/browser.php"]'), |
| 83 | + iframeContent.waitForURL(/\/browser\.php$/), |
| 84 | + ]); |
| 85 | + } finally { |
| 86 | + await page.close(); |
| 87 | + } |
| 88 | +} |
| 89 | +``` |
| 90 | + |
| 91 | +{{< /code >}} |
| 92 | + |
| 93 | +### Valid usage patterns for waitForURL |
| 94 | + |
| 95 | +Use one of the following patterns to coordinate the action that triggers navigation with waiting for the final URL. |
| 96 | + |
| 97 | +{{< code >}} |
| 98 | + |
| 99 | +<!-- eslint-skip --> |
| 100 | + |
| 101 | +```js |
| 102 | +await Promise.all([ |
| 103 | + frame.waitForURL('https://quickpizza.grafana.com/my_messages.php'), |
| 104 | + frame.locator('a[href="/my_messages.php"]').click(), |
| 105 | +]); |
| 106 | +``` |
| 107 | + |
| 108 | +{{< /code >}} |
| 109 | + |
| 110 | +or |
| 111 | + |
| 112 | +{{< code >}} |
| 113 | + |
| 114 | +<!-- eslint-skip --> |
| 115 | + |
| 116 | +```js |
| 117 | +const navPromise = frame.waitForURL('https://quickpizza.grafana.com/my_messages.php'); |
| 118 | +await frame.locator('a[href="/my_messages.php"]').click(); |
| 119 | +await navPromise; |
| 120 | +``` |
| 121 | + |
| 122 | +{{< /code >}} |
| 123 | + |
| 124 | +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: |
| 125 | + |
| 126 | +{{< code >}} |
| 127 | + |
| 128 | +<!-- eslint-skip --> |
| 129 | + |
| 130 | +```js |
| 131 | +await frame.locator('a[href="/my_messages.php"]').click(); |
| 132 | +await frame.waitForURL('https://quickpizza.grafana.com/my_messages.php'); |
| 133 | +``` |
| 134 | + |
| 135 | +{{< /code >}} |
| 136 | + |
| 137 | +### Best practices |
| 138 | + |
| 139 | +1. **Verify frame existence**: Frames can be created, destroyed, or replaced during page navigation. Always verify frame existence before calling `waitForURL()`. |
| 140 | + |
| 141 | +2. **Use appropriate selectors**: Use frame selectors that are stable and unique. |
| 142 | + |
| 143 | +3. **Handle cross-origin scenarios**: Be aware of limitations when working with cross-origin iframes. |
| 144 | + |
| 145 | +4. **Combine with content verification**: After URL change, verify that the expected content is present. |
| 146 | + |
| 147 | +5. **Consider frame timing**: Frame navigation may happen after page navigation, so allow appropriate time. |
| 148 | + |
| 149 | +### Common use cases |
| 150 | + |
| 151 | +- **Payment processing**: Waiting for payment iframe redirects |
| 152 | +- **Social media embeds**: Handling navigation in embedded social content |
| 153 | +- **OAuth flows**: Managing authentication within iframes |
| 154 | +- **Multi-frame applications**: Coordinating navigation across multiple frames |
| 155 | +- **Embedded widgets**: Testing third-party widget navigation |
| 156 | + |
| 157 | +### Related |
| 158 | + |
| 159 | +- [frame.waitForNavigation()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/frame/waitfornavigation/) - Wait for frame navigation events |
| 160 | +- [frame.waitForLoadState()](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-browser/frame/waitforloadstate/) - Wait for load states |
0 commit comments