Stale Element Reference

Using hard waits like WebUI.delay() is a cardinal sin of test automation, and will be the bane of your existence as an automation engineer. Never use them. The only reason to use a hard wait like that is to confirm that you have a timing issue, after which you need to implement a legitimate wait condition to handle it. (Also, I see that they are commented out, so I’m not sure that you are even waiting the 2 seconds like you’re intending to).

This is an art in it’s own right, but usually it involves waiting for some condition on the page to be true. If your application has a spinner or an overlay of some sort that appears when it’s loading, it’s easy enough to wait for that to disappear, indicating that the page is ready for further input. If you’re not that lucky, you’ll have to watch for specific elements and/or attributes in the DOM to appear/disappear, indicating that the page is in a static state. See the built-in WebUI.waitForElement___() family of methods.

Now, as for your specific issue, it violates point #1 that I made above. When you do something like this:

def rowArray = WebUI.executeJavaScript('return document.querySelectorAll(\'#data-table tbody tr td:nth-child(' + (columnNumber + 1).toString() + ')\')', null)

You get a reference to an array of elements, and you are reusing this reference multiple times. While you iterate through these elements and do work, your page has plenty of time to potentially reload, which would completely invalidate your list. There are two ways to mitigate this:

1.) Re-locate the list of elements after each iteration:

def rowArray = WebUI.executeJavaScript('return document.querySelectorAll(\'#data-table tbody tr td:nth-child(' + (columnNumber + 1).toString() + ')\')', null)
for (def row : rowArray) {
    String rowValue = row.text
    println rowValue
    if (value.toUpperCase()!= rowValue.toUpperCase()) {
        WebUI.comment(rowArray.toString())
        WebUI.comment(reportName + ': ' + type + ' report not all ' + type + 's match!')
        assert false
    }
    rowArray = WebUI.executeJavaScript('return document.querySelectorAll(\'#data-table tbody tr td:nth-child(' + (columnNumber + 1).toString() + ')\')', null)
}

2.) (Preferred method) Grab the size of the array once, then grab each row individually by index and get the text:

def size = WebUI.executeJavaScript('return document.querySelectorAll(\'#data-table tbody tr td:nth-child(' + (columnNumber + 1).toString() + ')\').length', null)
for (i = 0; i < size; i++) {
    def row = WebUI.executeJavaScript('return document.querySelectorAll(\'#data-table tbody tr td:nth-child(' + (columnNumber + 1).toString() + ')\').item(' + i + ')', null)
    String rowValue = row.text
    println rowValue
    if (value.toUpperCase()!= rowValue.toUpperCase()) {
        WebUI.comment(rowArray.toString())
        WebUI.comment(reportName + ': ' + type + ' report not all ' + type + 's match!')
        assert false
    }
}

(You should probably check my JavaScript here, I don’t normally use it for element location.)