grafana / xk6-browser

The browser module adds support for browser automation and end-to-end web testing via the Chrome Devtools Protocol to k6.
https://grafana.com/docs/k6/latest/javascript-api/k6-browser/
GNU Affero General Public License v3.0
344 stars 41 forks source link

Fix underlying `frame.waitForSelector` #1534

Closed ankur22 closed 2 weeks ago

ankur22 commented 2 weeks ago

What?

This fixes an issue with APIs that use the underlying frame.waitForSelector. It does this by reusing frame.waitFor which contains a fix to retry on certain errors which can occur when a navigation is taking place while also waiting for the selector.

Why?

This makes several APIs more robust when called during or after a navigation to a new page. I believe the list covers most of the APIs that this fix applies to:

Tests that works with fix (but not without) Test that used to fail on reading the `textContent` of the `h2` header. ```js import { browser } from 'k6/browser'; import { check } from 'https://jslib.k6.io/k6-utils/1.5.0/index.js'; export const options = { scenarios: { ui: { executor: 'shared-iterations', options: { browser: { type: 'chromium', }, }, }, }, thresholds: { checks: ["rate==1.0"] } } export default async function() { const context = await browser.newContext(); const page = await context.newPage(); try { await page.goto('https://test.k6.io/', { waitUntil: 'networkidle' }); const wait1 = page.locator('input[name="login"]').waitFor(); await page.locator('a[href="/my_messages.php"]').click() await wait1; await page.locator('input[name="login"]').type('admin'); await page.locator('input[name="password"]').type("123"); const wait2 = page.locator('h2').waitFor(); await page.locator('input[type="submit"]').click(); await wait2; await check(page.locator('h2'), { 'header': async lo => { return await lo.textContent() == 'Welcome, admin!' } }); } finally { await page.close(); } } ``` Test that used to fail when working with `waitForSelector`. ```js import { browser } from 'k6/browser'; import { check } from 'https://jslib.k6.io/k6-utils/1.5.0/index.js'; export const options = { scenarios: { ui: { executor: 'shared-iterations', options: { browser: { type: 'chromium', }, }, }, }, thresholds: { checks: ["rate==1.0"] } } export default async function() { const context = await browser.newContext(); const page = await context.newPage(); try { await page.goto('https://test.k6.io/', { waitUntil: 'networkidle' }); const wait1 = page.waitForSelector('input[name="login"]'); await page.locator('a[href="/my_messages.php"]').click() await wait1; await page.locator('input[name="login"]').type('admin'); await page.locator('input[name="password"]').type("123"); const wait2 = page.waitForSelector('h2'); await page.locator('input[type="submit"]').click(); await wait2; await check(page.locator('h2'), { 'header': async lo => { return await lo.textContent() == 'Welcome, admin!' } }); } finally { await page.close(); } } ```

Checklist

Related PR(s)/Issue(s)

Related: https://github.com/grafana/xk6-browser/pull/1469 Fixes: https://github.com/grafana/k6/issues/4048