grafana / xk6-browser

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

A connect method on each test iteration #1032

Open ankur22 opened 1 year ago

ankur22 commented 1 year ago

Feature Description

Prior to v0.46.0 of k6, there used to be a chromium.connect method which allowed users to connect to remote chrome instances that are running locally or remotely elsewhere. This meant that users would take full responsibility of the life cycle of chrome on every test iteration.

After the release of v0.46.0 of k6, we removed chromium.connect but added in an env var (K6_BROWSER_WS_URL) to allow users to still connect to those remote chrome instances. Note that this env var can take multiple websocket connections as long as they're separated with a ,.

There is one use case which we didn't take into account which is where users of lambda test needed to remotely connect to a chrome browser farm where the capabilities on each iteration could change. An example can be found here.

Example lambda test + k6 script ```js import { chromium } from 'k6/experimental/browser'; import { check } from 'k6'; import { htmlReport } from "https://raw.githubusercontent.com/benc-uk/k6-reporter/2.4.0/dist/bundle.js"; export let options = { vus: 3, iterations: 4 } export default async function () { const capabilities = [ { "browserName": "Chrome", "browserVersion": "latest", "LT:Options": { "platform": "Windows 11", "build": "K6 Build", "name": "K6 Test", "user":`${__ENV.LT_USERNAME}`, "accessKey":`${__ENV.LT_ACCESS_KEY}`, "network": true, "video": true, "console": true, "tunnel": false } }, { "browserName": "Chrome", "browserVersion": "latest", "LT:Options": { "platform": "MacOS Ventura", "build": "K6 Build", "name": "K6 Test", "user":`${__ENV.LT_USERNAME}`, "accessKey":`${__ENV.LT_ACCESS_KEY}`, "network": true, "video": true, "console": true, "tunnel": false } } ]; capabilities.forEach(async (value) => { console.log(' URL formed is ' + JSON.stringify(value)) const wsURL = `wss://cdp.lambdatest.com/k6?capabilities=${encodeURIComponent(JSON.stringify(value))}` const browser = chromium.connect(wsURL); const context = browser.newContext(); const page = context.newPage(); await page.goto('https://ecommerce-playground.lambdatest.io/index.php?route=account/login'); page.screenshot({ path: 'screenshots/browserTestScreenshot.png' }); page.locator('#input-email').type('lambdatest.Cypress@disposable.com'); page.locator('#input-password').type('Cypress123!!'); const submitButton = page.locator('input[value="Login"]'); await Promise.all([page.waitForNavigation(), submitButton.click()]); check(page, { 'Verify user is logged In': () => page.locator('.breadcrumb-item.active').textContent() == 'Account' }); check(page, { 'Verify the text': () => page.locator('.breadcrumb-item.active').textContent() == 'Test' }); page.close(); browser.close(); }); } export function handleSummary(data) { return { 'TestReport.html': htmlReport(data, { debug: true }) }; } ```

The capabilities are defined, encoded to URI, and added to the query parameter capabilities in the websocket connection url:

const wsURL = `wss://cdp.lambdatest.com/k6?capabilities=${encodeURIComponent(JSON.stringify(value))}`

This could still be possible while working with the env var K6_BROWSER_WS_URL, but it would have to be done outside the test script using something like a bash script to orchestrate the larger test suite. This isn't a good DX.

In k6 we would recommend working with scenarios, but the problem with scenarios is that there's no way to add fields which can be interrupted by the browser module before it connects to a remote browser.

How can we allow dynamic websocket urls per iterations that would work with the current setup of how the browser module works with chrome?

Suggested Solution (optional)

NA

Already existing or connected issues / PRs (optional)

NA

inancgumus commented 1 year ago

Should we expose and let connect accept a URL? This might also need further restructuring. This should be weighed against the uniformity of local and remote runs 🤔

ankur-lt commented 8 months ago

@ankur22 , any update on this?