I write a lot of automated tests. Most of the times, it all goes nice and smooth, like a good song. But once in a while i run into an automation situation that leaves me completely baffled. Debugging does not reveal how to fix it, and it is not very obvious to me what is going on. When do i realize what the issue was, i’m like ‘WOW i did not expect that’. These kind of stories are good to share, so that you know what to expect, should you encounter the same behavior. So, here is the peculiar, true story of Selenium, the StaleElementReferenceException, the iframe, the List and the WebElement.
It all starts with the fact that i need to automate a test scenario using Selenium. I need to interact with a WebElement on the page. This WebElement has a selector, which i will simply refer to as X. The WebElement is inside an iframe. But the X selector can be found multiple times on the entire page: at least once outside of the iframe (in the default content), and once inside of the iframe.
This test needs to work with only the WebElement defined by the X selector from within the iframe. However in some other tests, i need to work with other X selector WebElements from outside of the frame. Specifically, with the first and the second such WebElement. So, because of the need to use multiple WebElements whose selector is X, i decide to create a List of WebElements, to store all these WebElements at one go.
In my current test i need to click on the WebElement with selector X from within the iframe. Therefore, in the test, i use Selenium’s ‘click’ method on this WebElement. Because in the iframe there is only one element with selector X, that means i need to click on the first item in the List of WebElements. And that should work, since WebElements are lazily loaded in Selenium. That means, that when switching to inside the iframe, the test’s context is the HTML inside the frame. Therefore, logically, the first item in the List, in the context of the iframe, is the item i want to click on. That’s because when i click on the first item in the List, it’s selector is lazily loaded from within the iframe, and it gives me the item i am looking for. At least that is how it works when no iframes are involved: when multiple identical selectors exist on the page, a single WebElement for this selector, or a first WebElement in a List defined for the selector represent the same WebElement. So it should be the same when working with iframes. Right?
Wrong! StaleElementReferenceException. So debug starts, trying to figure out why this does not work. The logic is sound. But the test just throws this Exception every time i run it. Debug, debug, debug. The selector is correctly written. There is only one item with that selector inside the iframe. I am trying to access the first element of the List. So why doesn’t it work?
After quite a few minutes: but wait. Previously i had a different way of storing the WebElement selector. That was before i realized i would need to work with several WebElements that have the same selector. And that way was: i had only one WebElement defined corresponding to that selector, not a List. The List was supposed to be an improvement. So what happens when i revert to having only one WebElement corresponding to selector X?
Amazingly…the test passes. No more Exception. Everything works as expected. Wow. Ok, lesson learned: when working with iframes, if multiple HTML elements exist with the same selector (inside the iframe and in the default content), don’t use a List.