Search code examples
testingiframeautomated-testse2e-testingtestcafe

Elements not found after switching to iframe context in TestCafe


Original question:

using

browser.switchToFrame(iframeEl);

I can switch to a particular iframe window, and that's alright - clicking elements and etc works.

But, for whatever reason, using Selector when the iframe is the current context, does not work. I suspect that it's because switchToFrame is a method on the browser instance, and I'm using Selector function imported in such manner:

import { Selector } from 'testcafe';

My question is - if I want to select a particular element within the iframe using testcafe (to read its HTML attributes for example) - how should I approach it? Am I missing something?

More details from GitHub thread:

More details: I'm creating an iframe with remote src, and to that iframe, I later inject some HTML, CSS, and JavaScript. I'm 100% sure that the iframe will have the DOM element that'd match my requested selector - but still, I get an error: Cannot obtain information about the node because the specified selector does not match any node in the DOM tree.

My code looks roughly like this:

const iframeEl = await Selector('a-iframe_inner[name="something"]');
    if (await iframeEl.count === 0) {
      await this.fBrowser.switchToMainWindow();
    } else {
      await this.fBrowser.switchToIframe(iframeEl);
    }

const something = await Selector('.something');

And on a line with await Selector the code breaks. In my other tests, where I'm also accessing the iframe and click some element using await browser.click(someOtherThing); it works flawlessly. I can also read the console state of the iframe without hassle.

I suspect that the content of the iframe element might not be ready yet, but I'm wondering how can I wait until it's ready? I've tried setting a timeout option to the Selector call, but it didn't change anything. Can you share any tips on how to delay getting a selector after switching to iframe context?

Solution:

Turned out that it was indeed a bug on my part. Sorry. For future gens: Iframe switching and using selectors should work all fine, at least in TestCafe v0.20.1. Just make sure that your selectors match and you are really in iframe context, not just think that you are there


Solution

  • There is no need to do anything special to make Selectors work in iframes. It should work as expected. If they do not wish to create a bug report in the official repository using this form, I would appreciate it if you provide an example that demonstrates the issue. As for your question, I was not able to reproduce this problem in a simple example. Test page:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <h1>Click me</h1>
    
    <iframe id="frame" src="http://example.com" style="width: 500px; height: 500px;"></iframe>
    
    </body>
    </html>
    

    Test code:

    import { Selector } from 'testcafe';
    
    fixture `Selector in iframe`
        .page `../pages/index.html`;
    
    const selector = Selector('h1');
    
    test('test', async t => {
        await t.click(selector);
    
        console.log(await selector.innerText);
    
        await t.switchToIframe('#frame');
    
        await t.click(selector);
    
        console.log(await selector.innerText);
    });
    

    All clicks work as expected and I was able to get innerText of the Selector successfully. In addition, I would recommend you check what element really exists on a page, that Selector refers to the existing element and that the element has width and height greater than zero.