What I'm doing
I've been making a utility method to help me find and properly wait for Webelements in Selenium. so far its going well and I have a way to try all kinds of different locators, wait till a webelement is found and then wait untill the webelement is displayed/enabled all with timeouts and nice things like that.
Whats the problem then?
The problem is that I sometimes need to find Webelements after pages reload. I've read up on available solutions to the 'staleness' problem and I know how to solve it (using the old webelement I just found and clicked on I'll wait till it's stale before I search again) BUT I don't want to manually have to check wether a given webelement causes a page to reload. I've tried looking in the Webelement and Expected conditions class to see if there is any method that returns true if a given webelement causes a page reload. I've tried searching about it here and on google and gotten nothing useful. I wanted to know if its possible to have something like this:
Boolean causesPageReload = webElement.causesPageReload;
With some imaginary method named causesPageReload
that determines wether a webelement causes a page reload when it is clicked on, submitted to, ect. I know that some webelements just cause javascript to run on the page and others reload the page but If i could programatically determine if it reloads the page I could just say:
if (causesPageReload){
wait.until(ExpectedConditions.stalenessOf("insert old webelement here"));
}
And solve the problem. Is there anything in the underlying HTML, javascript or maybe something already built in that could provide this information? Sure I can manually go through the steps myself and see which webelements under test actually cause a page refresh, but that is subject to change, prone to human error and also time consuming.
Possible alternatives?
Alternatively I could just do my staleness check with a timeout of ten seconds and then if it reloads the page thats fine but if it doesn't it allows 10 seconds for the javascript or whatever to finish what it's doing. (I was also kinda wondering If I needed to wait for non page reloading webelement clicks as well but that seems harder due to javascript and entails a different question) I don't know if I would need to wait if the page isn't going to reload. even if I knew that I did need to wait in the non reload case, I wouldn't know how to. My current waits just wait for the webelement to be found, displayed and enabled so if clicking on it causes something important (that I need to wait for) but doesn't change those things, I'd need something else but that requires another question to be more in depth.
Tl:Dr
I just need to know if I can find out which webelements cause pages to reload programatically and if I can't then is there any need to wait for the non reloading ones (no need to go all in depth about the second case just tell me how to ask that as a second question later)?
Update
I've tried multithreading this and so far I've gotten something that can (in a timely manner) decide wether a given element when clicked changes in the DOM or doesn't. This covers most page reloading cases but might lead to a false positive since I'm pretty sure there are other instances where Element references go stale that don't involve the page reloading. I think the root cause of the problem is there is no data/flag/hook to grab onto to really tell. I suppose a better hook would lead to a better solution but I have no idea what that hook would be. On the bright side I did learn/become familiar with alot of multithreading which is good because its an area I've been weak in. I'm going to try to research the javascript thats been mentioned in answers and see If i can't combine that with my multithread approach. Once I have a good hook all I'd need to change is an ExpectedConditions call on a WebDriverwait waiting object.
Update 2
I found this website: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
Which details "load" and "DOMcontentloaded" events. Two things in javascript that fire when pages are loaded/reloaded. I have already created a thread application with ExpectedConditions like so:
WebDriverWait wait = new WebDriverWait(driver,timeoutSeconds);
try{
wait.until(ExpectedConditions.stalenessOf(webElement));
}
catch (TimeoutException e){
}
Thus I'm pretty sure I can modify the wait.until line to check for a javascript event firing with a timeout using a Java to Javascript interface. To use the two langauges together I was led to this question:
How can I use JavaScript in Java?
In order to obatin knowledge on how that basically works. I'm going to try to implement this using Nashorn or maybe some other interface depending on whats the best.
What this potentially means
While this doesn't determine for us wether a given webelement causes page reloading BEFORE actually "trying" it, it does determine it just by "trying" the webelement. And, because I used a thread off of main, my check for "no it didn't reload the page" is effectively just the timeout condition which can be configured as needed. I don't think its possible to determine if a Webelement causes a page reload without actually trying it, but at least we can try it, determine if it reloads within a timeout period and then we will know we will have waited sufficiently long enough to not get any stale reference exceptions when searching for the same or a next element if we at least know that the next element we're looking for exists on the new page (assuming that once we execute the method to try to locate it, it waits for said element to be displayed and selectable but I've already done that). This also allows us to determine if a given webelement was deleted from the page by "trying it" because if we combine the javascript pageload call with the stalereference check I already have, then we can use the condition of "the JS load event didn't fire (page static) BUT stalereference excpetion was thrown (DOM element changed)" as the check for "this element was deleted/changed signifigantly but page wasn't reloaded", Which is quite useful information. Additioanlly since these elements can now be grouped into three categories:
- Doesn't get deleted, can reference again
- Deleted but page static
- Deleted but page changes
We can store the results beforehand and (as long as the locators remain intact) we can more easily know wether we must wait or not after clicking the webelement. We could even go further and if we know we have the 2nd case, we could retry locating the element and see if it's locators change or not when we click it since I think stalereference exceptions can be thrown without requiring all the locators to change. How useful this is? I'm not sure but I think its pretty useful stuff but somehow I don't think I'm the first one to try/find a solution for this. I will post an answer when I successfully implement and test this but it will be awhile because I need to learn some basic Javascript and then how to integrate that with my java.