Click elements within an iframe

hi team, i try to click a button with an iframe but it doesn’t work.
Curiously, I can even get the text of this button, so I think the element should be located correctly.

getConvFrame(frameName){
		let fr;
		while(!fr){
			let frames = this.page.frames()
			frames.forEach(function(frame){
			  console.log(`frame.title() is ${frame.title()}`)
			  if(frame.title().includes(frameName)){
				  console.log("###Load Conversation Frame Completed###")
				  fr=frame
			  }
			})
			this.page.waitForTimeout(3*1000)
		}
		return fr
	}

I can get the buttonText correctly as follows:

const convFrame = getConvFrame("xxxxxFrame") 
const buttonText = await convFrame.textContent(coverPage.newConverButton)
page.waitForTimeout(3*1000)
console.log(`=========button text is ${buttonText}=======`)

However, when I try to click this button, it doesn’t work anyway.

console.log(`=========Click New Conver Button==========`)
convFrame.waitForSelector(coverPage.newConverButton)
const newConvButton = convFrame.$(coverPage.newConverButton)

await newConvButton.click()
await convFrame.click(coverPage.newConverButton)

Seems like we can only get the text, but for click action, it’s not support yet?

Hi @metoto , welcome to the forum! :wave:

Could you please post the full script so we can understand better what is going on and reproduce the issue? Does it reference a publicly accessible site?

From your explanation I understand that you are able to get the text content of the button that you want to select through selector coverPage.newConverButton in:

const buttonText = await convFrame.textContent(coverPage.newConverButton)

But are you able to select the button element through:

const newConvButton = convFrame.$(coverPage.newConverButton)

?
I would recommend using frame.locator() method instead of $ here.

Can you post the full test output also?
Thank you.

thanks a lot for reply, you mention we can use the frame.locator() ? I’m not sure since I did not find this method in document Frame

Right, thanks for the heads up! This is supported and should be documented.
We will work on adding it to the docs :+1:

finally i found the root cause, let me explain:
On my page, for example, the size of the window is 1280x800, and the frame is a part of the page, so it may be 800x500. when I get the position of the button on the frame, the x,y is incorrect, they are calculated as the relative position in the frame, but not the position for the page.
So when i use locator.click method, it takes no effect.

and I try the frame.locator(), it still not work, I’m not sure why since I can not capture the locator position.

Hi,
I am also trying to click to click captcha within an iframe but I couldn’t find a way to click an element within an iframe.
let frames = await page.frames();
for (const frame of frames) {
if (frame.title() === ‘reCAPTCHA’ && frame.name().startsWith(‘a’)) {
await frame.locator(‘[id=“#recaptcha-anchor”]’).click();
}
}

frame.locator() is not working. Getting the following error.
panic: GoError: dispose: canceled
running (00m36.5s), 1/1 VUs, 0 complete and 0 interrupted iterations
goroutine 90 [running]:-----------------------] 1 VUs 00m36.5s/10m0s 0/1 shared iters
go.k6.io/k6/js/common.Throw(...)

Hi @meteboyaci1,

For iframes, have you seen this answer.

Hope it helps.

Hi, I already get the iframe and get methods are working in it. But action methods like click is not working within the iframe. Below you can see two different options I tried. And also you can see the errors i got for each attempt.
1.
export default async function() {
const page = browser.newPage();

try {
    await page.goto('https://**************#/sign-in', { waitUntil: 'networkidle' });
    page.screenshot({ path: 'screenshot.png' });

    const acceptCookies = page.locator('button[id="*******"]');
    await acceptCookies.click();

    await page.locator('input[type="email"]').type('***********');
    await page.locator('input[type="password"]').type('********');

    document.querySelector('iframe').contentWindow.document.getElementById('#recaptcha-anchor').click();

} finally {
    page.close();
}

}

Error:
ERRO[0007] Uncaught (in promise) ReferenceError: document is not defined

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

try {
    await page.goto('https://**************#/sign-in', { waitUntil: 'networkidle' });
    page.screenshot({ path: 'screenshot.png' });

    const acceptCookies = page.locator('button[id="*******"]');
    await acceptCookies.click();

    await page.locator('input[type="email"]').type('*******');
    await page.locator('input[type="password"]').type('*******');

    // document.querySelector('iframe').contentWindow.document.getElementById('#recaptcha-anchor').click();

    let frames = await page.frames();
    for (const frame of frames) {
        if (frame.title() === 'reCAPTCHA' && frame.name().startsWith('a')) {

            // ---> Here I am able to get required iframe and when I want to get the frame content console.log('pppp: ' + await frame.content()) gives me the frame content. But I can not interact with iframe elements.
            frame.contentWindow.document.getElementById('#recaptcha-anchor').click();
        }
    }

} finally {
    page.close();
}

}

Error:
ERRO[0007] Uncaught (in promise) TypeError: Cannot read property ‘document’ of undefined

As I mentioned before I want to click an element within an iframe. But it seems i can not find any element within an iframe at the moment.

Thanks.

Hi @meteboyaci1,

It’s not possible to access document directly in a test script. It’s because a test script runs in k6, not in the browser. Please see page.evaluate for running JavaScript within the browser’s context.

Hope this helps.

1 Like