Locating elements within an iframe

Is there a way to locate an element within an iframe?

I have used page.frame({ url: ‘mysourceurl’ }); within my xk6 test, but Powershell prints out

“Page.frame(frameSelector) has not been implemented yet”

Hey @jbx,

Unfortunately, we don’t support that feature (yet) :frowning: However, you can do something like the following:

import launcher from "k6/x/browser";

export default function () {
  const browser = launcher.launch('chromium', { headless: false })
  const page = browser.newContext().newPage();
  page.setContent(`
    <iframe></iframe>
    <span>outside</span>
  `);

  page.evaluate(() => {
    document.querySelector('iframe').contentDocument.write("<span>inside</span>")
  });

  console.log(page.evaluate(() => {
    return document.querySelector('iframe').contentWindow.document.getElementsByTagName('span')[0].innerText
  }));

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

When you execute the script using xk6-browser, it should return inside. Please let me know if it helps you.

Awesome! this workaround works fine! glad to bump this! :tada:

1 Like

Hi @inanc,

I’ve been trying your solution lately but got this error:

evaluating JS: DOMException: Blocked a frame with origin from accessing a cross-origin frame.

How can I resolve this solution?

Hi @minhhd,

Welcome to the forum.

Could you share your test script? It looks like the website under test is trying to access an iframe from a different origin, and it might be best to resolve that issue.

We do provide a workaround which should work if you add bypassCSP: true when creating a newContext:

const context = browser.newContext({
  bypassCSP: true
});

Cheers,
Ankur

1 Like

I was able to get this working with this code:

const iframeSelector = 'iframe[title="Stripe address form"]';
await page.waitForSelector(iframeSelector, { visible: true, timeout: 10000 });
const iframeElement = await page.$(iframeSelector);
const iframeContent = await iframeElement.contentFrame();

// Interact with form elements
await iframeContent.waitForSelector('input[name="name"]', { visible: true, timeout: 10000 });
await iframeContent.click('input[name="name"]');
await iframeContent.type('input[name="name"]', 'John Doe'); // <input type="text" />

Full example:

import { browser } from 'k6/browser'; // k6 v0.57.0 (go1.24.0, darwin/arm64)

export const options = {
  scenarios: {
    ui: {
      executor: 'constant-vus',
      vus: 1,
      duration: '10s',
      options: {
        browser: {
          type: 'chromium',
          bypassCSP: true,
          headless: true,
        },
      },
    },
  }
};

export default async function loadTest() {
  const page = await browser.newPage();

  try {
    await page.goto('http://localhost:3000');
    await page.locator('//h2[text()="Checkout Page"]').waitFor({ state: 'visible', timeout: 10000, });

    // Wait for the iframe to finish loading
    await page.waitForSelector('iframe[title="Stripe address form"]', { visible: true, timeout: 10000 });
    const iframeElement = await page.$('iframe[title="Stripe address form"]');
    const iframeContent = await iframeElement.contentFrame();
    // Interact with form elements
    await iframeContent.waitForSelector('input[name="name"]', { visible: true, timeout: 10000 });
    await iframeContent.click('input[name="name"]');
    await iframeContent.type('input[name="name"]', 'John Doe'); // <input type="text" />
    await iframeContent.locator('select[name="state"]').selectOption('NY'); // <input type="select" />
    // ...
  } finally {
    await page.close();
  }
}