1

What I'm doing

I've been experimenting with Selenium and making a simple program to make my Selenium testing life easier. Part of this is testing webelements and figuring out what methods (clicking submitting ect) make them reload the page, remain static, or become stale without reloading the page. In this question I'm particularly interested in the third case as the first two are already implemented by me.

The problem I'm having

The problem I have is finding a Webelement that goes stale and doesn't cause a page reload. I can't think of a good way to search for one, I don't have the HTML and javascript skills to make one (yet anyways) and I can't verify my code works unless I actually test it.

What I've done/tried

The first thing I thought to look for was a popup but those aren't actually part of the webpage and they're also quite unreliable. I want something thats going to behave consistently because otherwise the test won't work. I think dynamic Webelements, those that change their locators when acted upon will suit my needs but I have no good way of finding them. Any google results for "Self deleting webelement exmaple" or "Webelement goes stale doesn't cause page reload example" or similar, will only give me questions on stackoverflow like this one rather than what I want - concrete examples. The code I'm running simply waits for a staleReferenceException and for an onload event in javascript. If the staleReferenceException occurs but the onload event does not, then I know I've found a self-deleting / dynamic webelement (at least thats what I think is the proper way to detect this). Here is the code I'm running:

try {
    //wait until the element goes stale
    wait.until(ExpectedConditions.stalenessOf(webElement));
    //init the async javascript callback script
    String script = "var callback = arguments[arguments.length - 1];" +
            "var classToCall = 'SeleniumTest.isPageReloaded';" +
            "window.addEventListener('onload'," + "callback(classToCall));";
    //execute the script and wait till it returns (unless timeout exceeded)
    JavascriptExecutor js = (JavascriptExecutor) driver;
    //execute the script and return the java classname to call 
    //if/when the callback function returns normally
    String classToCall = (String) js.executeAsyncScript(script);
    clazz = Class.forName(classToCall);
    callbackMethod = clazz.getMethod("JavascriptWorking");
    callbackMethod.invoke(null,null);
    //page reloaded
    threadcase = 1;
}
//waiting until webElement becomes stale exceeded timeoutSeconds
catch (TimeoutException e) {
    //page was static
    threadcase = 2;
}
//waiting until webElement Reloaded the page exceeded timeoutSeconds
catch (ScriptTimeoutException e) {
    //the webElement became stale BUT didn't cause a page reload.
    threadcase = 3;

As you can notice above there is an int variable named threadcase in this code. The three 'cases' starting from 1 (0 was the starting value which represented a program flow error) represent the three (non-error) possible results of this test:

  1. the page reloads
  2. the page remains static, webelement doesn't change
  3. the page remains static, webelement changes

And I need a good example with which to test the third case.

Solutions I've considered

I've done some basic research into removing webelements in javascript but I A: don't even know if I can act on the page in Selenium like that and B: I'd rather get a test case that just uses the Webpage as is since introducing my edits makes the validity of my testcase reliant on more of my code (which is bad!). So what I need is a good way of finding a webelement that matches my criteria without having to scour the internet with the f12 window open hoping to find that one button that does what I need.

Edit 1

I just tried doing this test more manually, it was suggested in an answer that I manually delete a webelement at the right time and then test my program that way. What I tested was the Google homepage. I tried using the google apps button because when clicked it doesn't cause the whole page to reload. So my thinking was, I'll click it, halt program execution, manually delete it, run the rest of my code, and since no onload events will occur, my program will pass the test. To my suprise thats not what happened.

The exact code I ran is the below. I had my debug stop on the first line:

1   Method callbackMethod = null;
2   try {
3       //wait until the element goes stale
4       wait.until(ExpectedConditions.stalenessOf(webElement));
5       //init the async javascript callback script
6       String script = "var callback = arguments[arguments.length - 1];" +
7           "var classToCall = 'SeleniumTest.isPageReloaded';" +
8           "window.addEventListener('onload', callback(classToCall));";
9       //execute the script and wait till it returns (unless timeout 
10      //exceeded)
11      JavascriptExecutor js = (JavascriptExecutor) driver;
12      //execute the script and return the java classname to call if/when 
13      //the callback function returns normally
14      String classToCall = (String) js.executeAsyncScript(script);
15          clazz = Class.forName(classToCall);
16          callbackMethod = clazz.getMethod("JavascriptWorking");
17          callbackMethod.invoke(null,null);
18          //page reloaded
19          threadcase = 1;
20      }
21      //waiting until webElement becomes stale exceeded timeoutSeconds
22      catch (TimeoutException e) {
23          //page was static
24          threadcase = 2;
25      }
26      //waiting until webElement Reloaded the page exceeded 
27      //timeoutSeconds
28      catch (ScriptTimeoutException e) {
29          //the webElement became stale BUT didn't cause a page reload.
30          threadcase = 3;
31          //trying to get the class from javascript callback failed.
32      }

whats supposed to happen is that a Stale webelement causes the program to stop waiting on line 4, the program progresses, initializes the Javascript callback in lines 6-11 and then on line 14 the call to executeAsyncScript is SUPPOSED to wait untill an 'onload' event which should only occur if the page reloads. Right now its not doing that or I'm blind. I must be confusing the program flow because I'm 99% certain that there are no page reloads happening when I manipulate the DOM to delete the webelement I'm clicking on.

This is the URL I'm trying:

https://www.google.com/webhp?gws_rd=ssl

Simple google homepage, the button I'm deleting is the google apps button (the black 9-grid in the top right)

some info on that element:

class="gb_8 gb_9c gb_R gb_g"

id="gbwa"

Its the general container element for the button itself and the dropdown it creates. I'm deleting this when my program hits the STOP on line 1. Then I go through my program in the debugger. Note (you may have to click inspect element on the button more than once to focus in on it). I'm going to try deleting lower level elements rather than the whole container and see if that changes anything but still this behavior baffles me. The goal here is to get the program flow to threadcase 3 because thats the one we are testing for. There should be no page reloads BUT the webelement should become stale after I manually delete it. I don't have any clue why the javascript callback is running when I can't see a page reload. Let me know if you need more info on what exactly I'm deleting on the google homepage and I'll try sending a picture (with optional freehand circles of course).

Community
  • 1
  • 1
Redacted
  • 613
  • 6
  • 23
  • Try [this example](https://demos.telerik.com/kendo-ui/dropdownlist/cascadingdropdownlist). It's a series of dropdowns. You could also try some car site where you choose the make, which fills the model dropdown. Depending on how they are created, you can probably find an example of what you are looking for. – JeffC Oct 01 '18 at 15:45

1 Answers1

1

I would think that you could debug through a test, place a breakpoint at a suitable point, then use the browsers dev tools to manually update the HTML.

Obviously, if you want this to be a repeatable process it is not an option, but if you are just investigating, then a manual intervention could be suitable

Robbie Wareham
  • 3,380
  • 1
  • 20
  • 38
  • Would I just delete the button HTML that I click in selenium? I've never really gotten into editing the DOM but I'll try this now and see if it suits my needs – Redacted Oct 01 '18 at 12:57
  • You can edit the DOM in any way to wish. I thought it was the 3rd option you want; element stays but changes? – Robbie Wareham Oct 01 '18 at 14:19
  • I tried to do this and for some reason my code doesn't halt for executeAsyncScript when its suppsoed to. That code should be halted untill an onload event occurs and for some reason its not doing that – Redacted Oct 01 '18 at 17:12
  • Async by definition shouldn't wait. – Robbie Wareham Oct 01 '18 at 20:10
  • but when I read this question: https://stackoverflow.com/questions/13452822/webdriver-executeasyncscript-vs-executescript I was under the impression that it did indeed wait. Also I don't know why it wouldn't since the program can't complete if the callback function hasn't been called. It would have to wait for the callback otherwise the return value would be null and/or invalid – Redacted Oct 02 '18 at 10:52
  • Fair enough. I have never had the need to use async when executing JS in webdriver so wasn't aware that it still blocked. I took the async to be literal! – Robbie Wareham Oct 02 '18 at 11:48
  • Yeah thats what I thought too! but the more I thought about it the more I realized that the program flow just wouldn't work. This does beg the question though, why is the onload event firing when I delete the element from the DOM? Surely just making HTML edits doesn't actually cause an onload event right? There must be something wrong with how I'm using the onload event here I just don't yet know what it is. – Redacted Oct 02 '18 at 12:05