Handling Exceptions from within Closures

I have no idea why my try/catch block isn’t working, and what reasonable alternatives there are to it:

def findDataRows = {    WebElement container     try {        container = driver.findElement(By.cssSelector('.tab-pane.active'))    }       catch (NoSuchElementException ex) {         container = driver.findElement(By.cssSelector('.dataTables_wrapper'))    }    String dataRowsSelector = '.dataTables_scrollBody tbody tr:not(.dataTables_empty):not(.group)'    List<WebElement> tableRows = container.findElements(By.cssSelector(dataRowsSelector)),        dataRows = new LinkedList<WebElement>()    for (WebElement tr : tableRows) {        if (tr.findElements(By.cssSelector('.dataTables_empty')).empty) {            dataRows.add(tr)        }    }    dataRows}

My question was initially asked on StackOverflow.

FWIW, since I’m not a Groovy expert, that code looks good to me.

But for that type of thing, I’d dispense with driver.findElement code and ask the page directly using JavaScript/CSS selectors. Then you won’t need to catch exceptions. In JS, there’s nothing “exception-worthy” about requesting a reference to a non-existent HTML element – happens all the time.

If I were to give you the two HTML code scenarios that my test case has to handle, could you walk me through the JavaScript/CSS selector way of doing this?

UPDATE: I found the documentation to execute JavaScript and return WebElements. https://docs.katalon.com/display/KD/[WebUI]+Execute+JavaScript

Sorry, missed your previous response.

As a taster, I made my own wrapper over WebUI.executeJavaScript – it adds a few utilities for each call (like a mini/poor-man’s jQuery).

public class js {

  /**
   * Execute JavaScript.
   * @param jsString (String) The JavaScript code to be executed.
   * @param args (List) Arguments to be passed to JavaScript.
   * @return The result returned from JavaScript.
   */
  static Object jsexec(String jsString, List<Object> args) {
    String js = '''
    function $$(selector, frmSelector) {
      if(frmSelector) {
        return getFrameElement(frmSelector, selector);
      }  
      return document.querySelector(selector); 
    }
    function $$prop(selector, prop, frmSelector) {
      if(frmSelector) return getFrameProp(frmSelector, selector, prop);
      var el = $$(selector);
      var style = window.getComputedStyle(el);
      return style.getPropertyValue(prop);
    }
    function getFrame(selector) { return document.querySelector(selector); }
    function getFrameDoc(selector) { return getFrame(selector).contentDocument;}
    function getFrameElement(frmSelector, selector) {
      return getFrameDoc(frmSelector).querySelector(selector);
    }
    function getFrameProp(frmSelector, selector, prop) {
      var frame = getFrame(frmSelector),
          el = frame.contentDocument.querySelector(selector),
          style = frame.contentWindow.getComputedStyle(el);
      return style.getPropertyValue(prop);
    }
    ;;
    '''
    js += $/
    try {
      ${jsString}
    } catch(e) {
      console.log('JS in Groovy ***ERROR*** - ' + e.message);
      return e.message; 
    }
    /$
    def result = WebUI.executeJavaScript(js, args)
    if(result.toString().startsWith("JS in Groovy")) {
      KeywordLogger log = new KeywordLogger()
      log.logError(result.toString())
      comment(result.toString())
    }
    return result
  }

I should point out, I’ve never seen “JS in Groovy ***ERROR***” printed anywhere and I can’t figure out why. Even with completely bogus code sent to it.

So the only significant line above is WebUI.executeJavaScript(…)

Here’s a trivial consumer:

  static String jsGetText(String selector) {
    comment('jsGetText: Retrieving text from ' + selector)
    String js = '''
      return $$(selector).innerText;
    '''
    return jsexec(js, Arrays.asList(selector))
  }

Good luck!