How to get authenticated browser instance before test

Hello, dear k6 community!
I’m recently joined on the board and I glad to use this framework for daily performancre testing.

At the moment I have one question, that I can’t resolve on my own. I would grateful to some advice from developers or more experienced user than I am.

Question is next:

I created simple scenario like this:

import { chromium } from 'k6/x/browser';
import { sleep } from 'k6';

export const options = {
  scenarios: {
    go_to_statistics_page: {
      tags: { name: 'statistics'},
      executor: 'constant-vus',
      exec: 'go_to_statistics_page',
      vus: 1,
      iterations: '1',
      maxDuration: '30s',
      startTime: '0s',
      gracefulStop: '10s'
    },

    go_to_incidents_archive_page: {
      tags: { name: 'incidents_archive_page'},
      executor: 'constant-vus',
      exec: 'go_to_incidents_archive_page',
      vus: 1,
      maxDuration: '30s',
      iterations: '1',
      startTime: '80s',
      gracefulStop: '40s'
    },

and more similar tests in this scenario

examples of tests function are represented below:

export function go_to_statistics_page() {

 const browser = chromium.launch({ args: ['no-sandbox', 'remote-debugging-port=9223'], headless: 
  true, timeout: '5m', });
  const context = browser.newContext({ ignoreHTTPSErrors: true, })
  const page = context.newPage();

  page.goto('https://' + __ENV.SENSOR_IP + '/#/login');

  page.waitForSelector("#e-login-page_login");
  page.type("#e-login-page_login", "Administrator");

  page.waitForSelector("#e-login-page_password");
  page.type("#e-login-page_password", "P@ssw0rd");

  page.waitForSelector("button#e-login-page_login-button");
  page.locator("button#e-login-page_login-button").click();

  page,goto('https://' + __ENV.SENSOR_IP + 
  '/#/main/r/dashboard;type=preset;interval=5;autoupdate=true')
  
  page.waitForSelector("//span[contains(text(), ' Incident severity levels '),  {visible: true, 'timeout': 30000})]
 
  console.log("Statistics Page is opened")

    page.close();
    browser.close();
};

export function go_to_incidents_archive_page() {

  const browser = chromium.launch({ args: ['no-sandbox', 'remote-debugging-port=9223'], headless: 
  true, timeout: '5m', });
  const context = browser.newContext({ ignoreHTTPSErrors: true, })
  const page = context.newPage();

  page.goto('https://' + __ENV.SENSOR_IP + '/#/login');

  page.waitForSelector("#e-login-page_login");
  page.type("#e-login-page_login", "Administrator");

  page.waitForSelector("#e-login-page_password");
  page.type("#e-login-page_password", "P@ssw0rd");

  page.waitForSelector("button#e-login-page_login-button");
  page.locator("button#e-login-page_login-button").click();

  page.goto('https://' + __ENV.SENSOR_IP + '/#/main/r/incidents/archive')
  page.waitForSelector("//div[@class='ag-center-cols-viewport' and @ref='eCenterViewport']", 
  {'visible': true, 'timeout': 30000});
    
   console.log("Incidents Page is opened")

    page.close();
    browser.close();
};

As you can see tests have repetitive actions of creating new browser instance and login that i would like to reduce and use them only once before all tests.

What I tried to resolve it:

  1. It’s apparently to insert in the script setup() function and make login inside of it and then return browser instance to tests.
export function setup() {
  
  let login = "Administrator";
  let password = "P@ssw0rd";
  
  const browser = chromium.launch({ args: ['no-sandbox', 'remote-debugging-port=9223'], headless: 
  true, timeout: '5m', });
  const context = browser.newContext({ ignoreHTTPSErrors: true, })
  const page = context.newPage();
  
  page.goto('https://' + __ENV.SENSOR_IP + '/#/login').then(() => {
    page.waitForSelector('#e-login-page_login');
    page.type("#e-login-page_login", login);
    page.waitForSelector("#e-login-page_password");
    page.type("#e-login-page_password", password);
    return page.click('button#e-login-page_login-button');
  }).then(() => {
    page.screenshot({ path: 'screenshots/login' });
  }).finally(() => {
    page.close();
    browser.close();
  });
  
};

But when I try to reuse instance of browser from setuo() in tests I find that setupData is empty: {}

export function go_to_statistics_page(setupData) {
console.log(setupData)
}
  1. Also I tried to use predefined persistent context, that was created from another script.
    I found that there is issue on Github: Implement BrowserType.launchPersistentContext(userDataDir[, options]), that’s why

I created persistent context with another (not k6) JS-script:

import playwright from 'playwright';
import { test, expect } from '@playwright/test';

import os from 'os';
import fs from 'fs';
import path from 'path';

(async () => {

    const userDataDir = path.join(os.tmpdir(), 'browser-context', String('any-test'));
    const context = await playwright['chromium'].launchPersistentContext(userDataDir, { args: ['--remote-debugging-port=9222'], headless: true, ignoreHTTPSErrors: true });
    const page = await context.newPage();
    await page.goto('http://SENSOR_IP/#/login');
    await page.locator("id=e-login-page_login").fill('Administrator');
    await page.locator("id=e-login-page_password").fill('P@ssw0rd');
    await page.locator("id=e-login-page_login-button").click();
    await context.close();

})();

And then I tried to reuse it in k6 chromium launch :

import { chromium } from 'k6/x/browser';

export default function go_to_incidents_archive_page() {

  const browser = chromium.launch({ args: ['no-sandbox', 'remote-debugging-port=9223', "user-data- 
  dir=/tmp/browser-context/any-test/"], headless: 
  true, timeout: '5m', });
  const page = browser.newPage({ ignoreHTTPSErrors: true, });
  page.goto('https://' + __ENV.SENSOR_IP + '/#/main/r/incidents/archive');

But in this case it seems browser ignores ‘user-data-dir’ and doesn’t use provided profile, because it still appears on login page and does’t go to required URL

Maybe someone has already encountered such a problem and knows a way to solve it.

Sorry if my question is too long for reading, I tried to explain the problem in detail.

Thank you for advance!

Additionally my k6 environment is:

k6 v0.43.1 ((devel), go1.19.9, linux/amd64)
Extensions:
GitHub - grafana/xk6-browser: k6 extension that adds support for browser automation and end-to-end web testing via the Chrome Devtools Protocol v0.9.0, k6/x/browser [js]

1 Like