Wait for Ready State during AJAX calls

The applications we are testing may heavy use of AJAX HTTP calls to the server, as they are written in AngularJS. When the page is making these asynchronous calls, we have had success waiting for the page to return to the ready state. This is a method that we used extensively in Selenium tests in the past, and have recently implemented it as a custom keyword for Katalon. (We still use WebUI.waitForAngularLoad for page loading.)

	@Keyword
	def waitForReadyState(int seconds) {

		// wait one second for load to begin
		WebUI.delay(1)

		// wait some number of seconds for page to load
		WebDriver webDriver = DriverFactory.getWebDriver();
		final WebDriverWait wait = new WebDriverWait(webDriver, seconds);
		wait.until(ExpectedConditions.jsReturnsValue("return document.readyState==\"complete\";"));

	}

Unfortunately, the document.readyState property only tells you about the state of the document loading process. If the resident code (i.e. JavaScript) needs to perform further processing before the page is truly ready for use by the user, document.readyState is likely to lead you astray.

I am not disputing that you may have had great success with the code snippet you posted, but it would be naive to believe that that code will work for all pages running on all servers all across the internet.

Here is one scenario you may want to consider:

  1. You wait for document.readyState to return “complete”.
  2. Resident JavaScript code THEN fires of a fetch/ajax request for more page elements (perhaps to populate a table with items for sale).
  3. When those items are loaded, further calls are made to populate nested tables with “more info” about each item.

Your test scenario is to check that the “zoom image” function works when a user hovers over the “more info” box in the nested table. You problem now is, you thought the page was “ready” at stage 1 above, but it isn’t ready, as you can see – it doesn’t even have the table data yet.

1 Like

Thank you for the thoughtful response. We will look out for this. I agree it is not a silver bullet.

When I wrote the custom waitForReadyState, I was thinking of things as a developer, trying to predict what is happening in JavaScript, behind the scenes. (This is the same problem with waitForAngularLoad and waitForJQuery: testers do not always know when to use these because they cannot know for sure what is happening behind the scenes.)

After using waitForReadyState for a while, I had a personal epiphany: to start thinking of the test in terms of the user experience. What does the user see to know that an operation is complete. So, now, instead of our custom waitForReadyState, I am using more of:

waitForElementVisible
waitForElementAttribute
waitForElementClickable
waitForElementPresent
etc.

I realize now that these are far more powerful, because they handle many situations when AJAX is happening behind the scenes. These are what real users rely on when they are waiting for AJAX calls to complete. Using these has made my tests more reliable (and has reduced the temptation to hard code delays).

The waitForReadyState did help us get out of some trouble, but I think I will use it less and less going forward.

(On a side note, I really wish there was a WebUI.waitForElementText. Not sure why that is not implemented by Katalon.)

While I also don’t subscribe to the idea a silver bullet, we actually do have one of sorts for our AJAX-heavy apps:

new WebDriverWait(driver, 300, 100).until(new ExpectedCondition<Boolean>() {
						@Override
						public Boolean apply(WebDriver d) {
							JavascriptExecutor js = (JavascriptExecutor)d;
							return (Boolean)js.executeScript(
									"return !!window.jQuery && window.jQuery.active == 0");
						}
					});

Never tried with Angular, but maybe give it a shot :slight_smile:

2 Likes

Precisely, Harold. You nailed it.

Our “automation user” is a robot: a faithful, does-exactly-what-he’s-told, idiot. And he’s most idiotic when we neglect to hold his hand and teach him patience. :blush:

2 Likes

Hi, I have a requirement to test Angular application ( build on 7.x). I came across the below blog …

Can someone help me to create Katalon Specific Custom Keyword to handle it and share the groovy file… ???

Just for your information,

Hi @Kazurayam

I have a quick doubt to ask …. Does ngWebDriver / JProtractor support the latest Angular version -7.x

I don’t know. Please check it yourself.