Effectively pausing a Test Case until a page object is no longer on screen

I have a test case that I would like to effectively pause while an object is on screen, and continue when it is no longer visible. After initially using a hard delay with a large time value (which is obviously undesirable), I’ve tried the following two options:

Use a ‘Wait For Element Not Present’ command

Mobile.waitForElementNotPresent(findTestObject('Page Object'), 60)

However, this fails immediately because the element is present (although this seems contrary to the logic as described in the help documentation [WebUI] Wait For Element Not Present | Katalon Docs - though it’s likely that I’ve misunderstood the documentation).

Use a While Loop Statement

while (Mobile.verifyElementVisible(findTestObject('Page Object'), 5, FailureHandling.CONTINUE_ON_FAILURE) == true) {
    Mobile.delay(5, FailureHandling.CONTINUE_ON_FAILURE)
}

Whilst this works in a sense (whilst the page object is present, it will wait 5 seconds, and so on, and then continues the test when the page object is no longer present), the final Delay command is marked as a fail, causing the entire test case to be marked as a fail, despite actually behaving exactly as I want it to.

I would be grateful for any advice or suggestions on how to achive this - thank you!

My reading of the docs is the same as yours - this should work. The example given in the docs agrees, too. The source also implies it should work.

There is the possibility that the wording in the docs for waitForElementNotPresent() is confusing you. What should be made clear is difference between visibility and presence:

Wait for the given element to NOT present (appear) within the given time (in seconds).

Presence is not about the appearance or visibility of the element. Presence is about presence in the DOM, regardless of visibility.

For your purposes, you need to be certain the element in question is in fact being REMOVED from the DOM. If you are concerned only about visibility, then use waitForElementNotVisible().

If you’re certain you’re using the correct API, then it sounds like there may be a bug in waitForElementNotPresent(). Please report back with your comments/findings.

@Russ_Thomas thanks for your response, much appreciated.

I understand your distinction between Presence and Visibility. In my case this relates to a mobile app (built on the Xamarin framework), so I think that there’s no DOM as such.

Using the Spy Mobile tool, I’ve established that the page item I’m interested in is either visible to the end user or not, which directly corresponds to whether I see the object or not in the hierarchy when using the Spy Mobile tool.

Unlike web, where there are two distinct keywords ‘Wait for element not present’ and ‘Wait for element not visible’, with mobile, there is only ‘Wait for element not present’ (I’m guessing because of what I’ve described above?).

And going back to the issue I’m having with this command, I was certainly expecting the test to wait until the element changed from being present to not present (up to the timeout value), which is certainly not what’s happenning.

Could Katalon Staff please review this and advise accordingly? I’d be happy to raise a formal ticket if this is an issue, otherwise I’m happy to be educated about how to use this command, or find some other solution to my problem.

Thanks :slight_smile:

@vu.tran @vu.le Some clarity please, gentlemen?

I never use the keywords named “Wait for Element Not xxxx” as I do not understand how these would/should work.

The combination of 2 conditions: (if the element xxxxx) && (before timeout) AND the Logical negation (Not) derives 4 cases:

  1. NOT (the element DOES NOT xxxx && now is before timeout) → continue waiting
  2. NOT (the element DOES NOT xxxx && now is NOT before timeout) → return TRUE
  3. NOT (the element DOES xxxx && now is before timeout) → return FALSE, or continue waiting?
  4. NOT (the element DOES xxxx && now is NOT before timeout) → return FALSE

The case #3 is problematic. The name “Wait for Element Not xxxx” does not determine how the case#3 should result. The keyword name “Wait for Element Not xxxx” confuses me.


Kevin’s approach “Use While Loop Statement” makes better sense to me. Unfortunately his implementation has some defects.

I would show you my proposal for better implementation of “Use While Loop Statement”. The following code is free from the defects that @kevin.mcandrew1 mentioned:

  1. it uses minimum time unit of wait = 1 second. It does not wait unnecessarily long timeout (say, 5 seconds)

  2. It does not mark “FAILED” when timeout occured

Test Cases/kevinsCase:

import com.kms.katalon.core.testobject.ConditionType
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

import kevin.Waiter

TestObject makeTestObject(String selector) {
	TestObject tObj = new TestObject(selector)
	tObj.addProperty("css", ConditionType.EQUALS, selector)
	return tObj
}

TestObject button = makeTestObject("a#btn-make-appointment")

WebUI.openBrowser("https://katalon-demo-cura.herokuapp.com/")
WebUI.verifyElementPresent(button, 3)

// we will wait for the button to disapper somehow
int timeoutSeconds = 10
Boolean stillThere = Waiter.waitWhileElementIsPresent(button, timeoutSeconds)
if (stillThere) {
	KeywordUtil.markWarning("Element located by " +
		button.getObjectId() + " is still present after " +
		timeoutSeconds)
} else {
	KeywordUtil.logInfo("the button has disappeared")
}

WebUI.closeBrowser()

Keywords/kevin/Waiter.groovy

package kevin

import java.time.LocalDateTime

import com.kms.katalon.core.model.FailureHandling
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.util.KeywordUtil
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI


public class Waiter {
	private Waiter() {}
	
       /**
	 * wait while the element is present in the target web page
	 * will return false as soon as the element disappeared.
	 * will return true only if the element is present when the timeoutSecodns expires
	 * 
	 * @param tObj Test Object which locates the element of your interest in the web page
	 * @param timeoutSeconds e.g, 10 = ten seconds
	 * @return the presence of the element in the web page
	 */
	
	static Boolean waitWhileElementIsPresent(TestObject tObj, int timeoutSeconds) {
		LocalDateTime periodStart = LocalDateTime.now()
		LocalDateTime periodEnd = periodStart.plusSeconds(timeoutSeconds)
		while (WebUI.waitForElementPresent(tObj, 1, FailureHandling.OPTIONAL)) {
                    // use WebUI.waitForXXX keyword instead of WebUI.verifyXXX because the waitForXXX keywords does not mark "StepFailedException"
			if (LocalDateTime.now().isBefore(periodEnd)) {
				Thread.sleep(500)
			} else {
				return true
			}
		}
		return false   // the element has disappered before the timeout expires
	}
	
}

The test case worked as follows:

@kevin.mcandrew1

You should be able to modify my code so that it fits to your case (testing Mobile, not WebUI).

@kazurayam Thank you for putting together your solution, I really appreciate it. I had a quick go at adapting it for mobile and unfortunately I couldn’t get it to work (sure to be me), but I will make a further attempt when I have more time.

Thanks @Russ_Thomas for tagging in @vu.tran and @vu.le - it would be great also to get some clarity on the native commands.

The native commands named with “Not” (such as “waitForElementNotPresent”, “verifyElementNotPresent”) can not be explained clearly due to their inappropriate names. That is the problem, I think.