Switching to new opened tab with k6-browser

I have a browser test, where after clicking a button on home page a new browser tab opens up. I need to switch to new browser tab and perform further actions on some web elements in the test script.

I have tried to use bringToFront() to switch to new tab but it doesnt seem to be working for me. is it the right method to use to switch browser tab?

I cant provide the URL at the moment to reproduce the exact issue because its not a public web app.

However, the step that mentioned in summary is pretty much what happens.

// click on button to open the new browser tab:

  const openNewPage = page.locator(newPage);
  page.waitForSelector(newPage, { timeout: 60000, visible: true });
  openNewPage.click();
  console.log('Clicked on the button to open new browser tab');
  await sleep(5);

After performing following step:

  await page.bringToFront();
  console.log('Focused on the new Tab...');

when i check console.log('Current URL after opening editor: ', page.url()); in the next step, the URL is still of the previous page and not of the new tab page.

I am not sure if i am something wrong or need to change something here to make it work. would appreciate any help or suggestions.

xk6-browser version

k6 v0.46.0 (2023-08-14T13:23:26+0000/v0.46.0-0-gcbd9e9ad, go1.20.7, linux/amd64)

OS

Ubuntu

@rajjnish

After you click on the button which opens a new page, the page variable still refers to the previous page.
You can get all the tabs with:

      const pages=browser.context().pages();

So maybe you could try after the click:

      const pages=browser.context().pages();
      const newPage = pages[pages.length-1];
1 Like

Thanks @bandorko ,

I didnt mention it but already had tried this approach as well, but still wasn’t able to switch to the new tab: :frowning:

      const pages=browser.context().pages();
      const newPage = pages[pages.length-1];

       // Switch to the new tab
       await newPage.bringToFront();

@rajjnish
For me, when the button opens the new tab, it become the active tab. (I run with K6_BROWSER_HEADLESS=false environment variable, so I see the browser)
And also I can access the content of the new page with the newPage variable.

@bandorko ,
I have tried to run the test in headed mode with K6_BROWSER_HEADLESS=false the whole time to see what actually happens in the UI.
Initially when the new tab opens up, it shows up in the browser as active tab but in few seconds(like 3-4), it goes back to the old tab with all the approaches i tried so far.
and the console.log('Current URL after opening editor: ', page.url()); shows the old tab URL even when in the headed mode in UI during run time the new tab is active.

A bit unsure if i could try something else to debug.
Thanks a lot for the help!

@rajjnish

You should use newPage.url() insted of page.url() after you get newPage from browser.context() as I suggested above.

2 Likes

@bandorko , Thanks for helping out with this one.

I made few smaller mistakes while accessing the elements of new tab instances that were causing the issue. Now i am able to get the new tab url and the right screenshot of the page, which indicates the switching is working fine.
The problem is with the new page, that freezes for quite a long time when opening via k6 script but that doesnt happen while opening the page manually and that took more for me to debug and figure out… though not sure why via script the new page just freezes and not manually… trying to debug it further.

Really appreciate your help. being new to k6 has been quite a learning experience so far!
Cheers!

@bandorko @rajjnish
I think I’m facing somewhat similar problem, but unable to get it working.
I have raised following query and shared a code snippet.
Would you like to take a look if you are facing the same issue with latest k6 build.

It seems what you are missing here is switching specifically to the different page instances before checking the title:

You can try like this or something similar:

await newPage.bringToFront() // to switch the the page instance

can update this and retry, if this helps:

  const pages = browser.context().pages()
  for (let i in pages){
    await pages[i].bringToFront()
    console.log(`Title${i}`, pages[i].title())
    // just to verify the URL
  console.log('Current URL after switching', pages[i].url())
  }

@rajjnish @mstoykov
I tried with bringtoFront but it doesn’t help. It keeps complaining about null object.

Uncaught (in promise) TypeError: Cannot read property 'bringToFront' of undefined or null

I have tried with sleep (delay) added, that didn’t solve the issue. Tried with For Of loop instead of For In to avoid page index bug, it didn’t help.

Does this code works on other machines? It will help me diagnose, if it is build/code issue or machine specific issue.

It seems with K6, we can’t iterate over different browser page instances like we are trying to do here (for that browser automation tools like playwright, puppeteer etc can be useful but not k6).

The other alternative (to do what you are trying to do here) for k6 that worked for me was:

  const pages = browser.context().pages();
  const Page2 = pages[pages.length - 1];

  console.log("=========================");
  console.log('Current URL before switching: ', page.url())
  console.log(page.title());

  await Page2.bringToFront();
  console.log('Current URL after switching: ', Page2.url())
  console.log(Page2.title());
  console.log("=========================");

I am trying to do something similar as well. When I run in headfull mode, I see two tabs (pages) open in the browser. But browser.context().pages().length return 1 as the output.

Hi @shanjiv177,

Make sure that you’re using the latest k6 version. We fixed a similar (or maybe the same) problem earlier.

Let me know how it goes.

Mine was also returning 1, I found a workaround just adding a 1 second sleep to ensure the new page was loaded

        await address.click();
        sleep(1)
        const pages = context.pages();
        const Page2 = pages[pages.length - 1];

@alexcentorbi07, instead of using sleep (which we don’t recommend), it’s better to wait for a selector (a page element) or navigation using one of: waitFor([options]) | Grafana k6 documentation, waitForNavigation([options]) | Grafana k6 documentation, or waitForTimeout(timeout) | Grafana k6 documentation.