Search code examples
javaiframeselenide

Array Index out of bounds exception -1 when switching iframes using PhantomJS headless browser


I am using Selenide to write a browser test. Within this test I have to switch to a different iframe a couple of times. When I run this test with Chrome, it works perfectly. But when I use phantomjs, sometimes it works and sometimes it fails. I don't see a pattern in why it's failing.

This the error I am receiving:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
   at java.util.ArrayList.elementData(Unknown Source)
   at java.util.ArrayList.get(Unknown Source)
   at com.codeborne.selenide.impl.CollectionElement.getWebElement(CollectionElement.java:29)
   at com.codeborne.selenide.impl.SelenideElementProxy.dispatchAndRetry(SelenideElementProxy.java:82)
   at com.codeborne.selenide.impl.SelenideElementProxy.invoke(SelenideElementProxy.java:56)
   at com.sun.proxy.$Proxy1.getAttribute(Unknown Source)
   at automationFramework.PegaRulesetCheck.main(PegaRulesetCheck.java:8)

The java code is very long so I will only show part of, where it fails.

79. /*Get the list of iframes*/
80. List<SelenideElement> myIframes = $$("iframe");
81. System.out.println("Switching to iframe " + myIframes.get(myIframes.size() - 1).getAttribute("name"));

So for some reason, sometimes it fails, and sometimes it works. Very randomly. I am suspecting that line 80, creating a list of the iframes, is not always working. It could be that the list is created before the other iframes are dynamically created, therefore switching to the other iframe is not possible. But I don't know how to fix this.


Solution

  • Okay so I was able to solve this issue. My suspicion was right, sometimes the list is created before all of the iframes are dynamically loaded.

    So I was able to solve this problem by using a for loop which checks if the array contains iframes. If it doesn't contain iframes it will wait 100 milliseconds.

    /*Get the list of iframes*/
    List<SelenideElement> myIframes = $$("iframe");
    
    /* For loop that makes sure that the list of iframes is bigger than 0 */
    for (int i=1; myIframes.size() < 1; i++){
        Thread.sleep(100);
        myIframes = $$("iframe");
        /* if the script waits for 10 seconds, break out of the for loop. */
        if(i > 99){
            System.out.println("Breaking out of for loop, list of iFrames contains : " + myIframes.size() + " frame.");
            break;
        }
    }