WaitForElement - Don't wait

I am also facing the same problem as in this topic WaitForElement - does not work as required

I don’t understand why the wait function doesn’t wait according to the timeout set in the function(10 seconds). The wait function seems to just wait 1 second and then finish
I’m sure my path in findTestObject(…) is correct. Because I tried waiting in case the object already exists and the wait function found it.
If the object already exists and the wait function only works, then this function has no meaning anymore

Anyone who had the same problem as me and had a solution, let me know
Please!!!

Please create a sample Test Case that is runnable on other’s machine. The sample should reproduce your findings. Without a runnable sample code, it is difficulut to discuss productively.

After much testing, I noticed that this problem appears on Hybrid applications.
Specifically, on page Login (with format web_app), you create a wait() function to wait for an object to exist on page Home (with native_app format). When page Home starts to load, the wait() function immediately stops and returns no object found even though there is still some time to wait.
The wait() function must wait for the “timeout” that I have set up. But no, the wait is not done yet, the wait() function to return a result that is not found
With sample code, it’s just Katalon’s “Wait for Element Present” function

@thanh.tung.170861

Which version of Katalon Studio do you use?

Prior to v8.6.5 (possibly sinice v8.6.0) , WebUI.waitForElementPresent had a problem; it doesn’t wait at all.

http://forum.katalon.com/t/waitforelementpresent-doesnt-seem-to-be-waiting-any-more/86718/3

As the relase note v8.6.5 says, the problem should have been fixed at v8.6.5.

http://forum.katalon.com/t/new-release-katalon-platform-update-may-31-2023/89214

Why not you try it?

I tried with version 8.6.6, this problem still exists
The waitForElementNotPresent function still ends before the timeout expires
I set the timeout to 60 seconds, the wait function ends after 11 seconds(the same time when the application switches to a new page).
→ And of course the returned result is: Element ‘Object Repository/.etc.’ is present

Could you please use the other strategies. It is possible that the element is simply being hidden from the view but not actually being removed from the DOM

  1. waitForElementVisible
  2. waitForElementClickable

Let me know if it works for you

??? I think that the keyword is working as specified. Why do you think “the problem still exists” ?

The waitForElementNotPresent keyword will end as soon as the target element disappers. When the application switches to a new page after 11 seconds, the target element disappers. So the keyword will end. The keyword will wait until the timeout expires only when the target element remains present.

I am afraid that you misunderstood what the keyword does. The name “…NotPresent” might have confused you. The “waitForElementNotPresent” should rather be known as “waitForElementToDisappear”.

In the image above you can see:
I set the timeout to 20s, but the method waitForElementNotPresent only waits 0.319s

Does anyone know why?

I believe, Mobile.waitForElementNotPresent keyword is just buggy.

@Elly_Tran

The following is the source code of com.kms.katalon.core.mobile.keyword.builtin.WaitForElementNotPresentKeyword of Katalon Studio v10.2.0:

package com.kms.katalon.core.mobile.keyword.builtin

import groovy.transform.CompileStatic

import java.text.MessageFormat

import org.openqa.selenium.WebElement

import com.kms.katalon.core.annotation.internal.Action
import com.kms.katalon.core.mobile.keyword.internal.MobileAbstractKeyword
import com.kms.katalon.core.mobile.keyword.internal.MobileKeywordMain
import com.kms.katalon.core.keyword.internal.AbstractKeyword
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.model.FailureHandling
import com.kms.katalon.core.exception.StepFailedException
import com.kms.katalon.core.keyword.internal.SupportLevel
import com.kms.katalon.core.helper.KeywordHelper
import com.kms.katalon.core.configuration.RunConfiguration
import com.kms.katalon.core.mobile.constants.StringConstants

@Action(value = "waitForElementNotPresent")
public class WaitForElementNotPresentKeyword extends MobileAbstractKeyword {
    
    @CompileStatic
    @Override
    public SupportLevel getSupportLevel(Object ...params) {
        return super.getSupportLevel(params)
    }

    @CompileStatic
    @Override
    public Object execute(Object ...params) {
        TestObject to = getTestObject(params[0])
        int timeout = (int) params[1]
        FailureHandling flowControl = (FailureHandling)(params.length > 2 && params[2] instanceof FailureHandling ? params[2] : RunConfiguration.getDefaultFailureHandling())
        return waitForElementNotPresent(to, timeout, flowControl);
    }
    
    @CompileStatic
    public boolean waitForElementNotPresent(TestObject to, int timeout, FailureHandling flowControl) throws StepFailedException {
        return MobileKeywordMain.runKeyword({
            KeywordHelper.checkTestObjectParameter(to)
            timeout = KeywordHelper.checkTimeout(timeout)
            WebElement element = findElement(to, timeout * 1000)
            if (element == null) {
                logger.logPassed(MessageFormat.format(StringConstants.KW_LOG_PASSED_ELEMENT_NOT_PRESENTED, to.getObjectId()))
                return true
            } else {
                logger.logWarning(MessageFormat.format(StringConstants.KW_LOG_PASSED_ELEMENT_PRESENTED, to.getObjectId()))
                return false
            }
        }, flowControl, RunConfiguration.getTakeScreenshotOption(), to != null ? MessageFormat.format(StringConstants.KW_MSG_FAILED_TO_WAIT_FOR_ELEMENT_X_NOT_PRESENT, to.getObjectId()) : StringConstants.KW_MSG_FAILED_TO_WAIT_FOR_ELEMENT_NOT_PRESENT)
    }
    
}

The Mobile.waitForElementNotPresent methos is NOT waiting at all. When the target element is found present in the page, this keyword will quickly return false with message “the element is present”.

When I wrote this in Sep 2023, I was talking about the WebUI.waitForElementPresent keyword which worked fine.

Now, @thanh.tung.170861 showed his/her testcase script for the first time. I was surprised to find that his/her script was calling Mobile.waitForElementNotPresent keyword, which is buggy.

Hi all,

Thank you for reporting this. I have created the ticket for this and be back with any update soon.

Hi all,

Please help try to resolve this issue with our latest version 10.3.2 and let us know if it works/not work. Thank you

I made a diff to compare v10.2.4 and v10.3.0’s sources of Mobile.waitForElementNotPresent keyword:

--- /Users/kazurayam/katalon-workspace/katalon-studio-sources/versions/10.2.4/resources/source/com.kms.katalon.core.mobile/com/kms/katalon/core/mobile/keyword/builtin/WaitForElementNotPresentKeyword.groovy
+++ /Users/kazurayam/katalon-workspace/katalon-studio-sources/versions/10.3.0/resources/source/com.kms.katalon.core.mobile/com/kms/katalon/core/mobile/keyword/builtin/WaitForElementNotPresentKeyword.groovy
@@ -4,1 +4,0 @@
-
@@ -6,1 +5,2 @@
-
+import java.time.Duration
+import org.openqa.selenium.TimeoutException
@@ -8,1 +8,2 @@
-
+import org.openqa.selenium.support.ui.FluentWait
+import com.google.common.base.Function
@@ -10,5 +11,1 @@
-import com.kms.katalon.core.mobile.keyword.internal.MobileAbstractKeyword
-import com.kms.katalon.core.mobile.keyword.internal.MobileKeywordMain
-import com.kms.katalon.core.keyword.internal.AbstractKeyword
-import com.kms.katalon.core.testobject.TestObject
-import com.kms.katalon.core.model.FailureHandling
+import com.kms.katalon.core.configuration.RunConfiguration
@@ -16,1 +13,0 @@
-import com.kms.katalon.core.keyword.internal.SupportLevel
@@ -18,1 +14,1 @@
-import com.kms.katalon.core.configuration.RunConfiguration
+import com.kms.katalon.core.keyword.internal.SupportLevel
@@ -20,0 +16,4 @@
+import com.kms.katalon.core.mobile.keyword.internal.MobileAbstractKeyword
+import com.kms.katalon.core.mobile.keyword.internal.MobileKeywordMain
+import com.kms.katalon.core.model.FailureHandling
+import com.kms.katalon.core.testobject.TestObject
@@ -21,0 +21,2 @@
+import groovy.transform.CompileStatic
+
@@ -44,2 +46,34 @@
-            WebElement element = findElement(to, timeout * 1000)
-            if (element == null) {
+
+            boolean elementNotFound = false
+            try {
+                // In theory, it should take 1.5 seconds each time it finds the element
+                // (1s to search and 500ms to sleep). But in reality, finding the element can take longer than 1s
+                // because the core implementation of `findElement` method (`findElementsByLocatorStrategy` method in MobileCommonHelper class)
+                // only checks the timeout after finding
+                elementNotFound = new FluentWait<TestObject>(to)
+                    .pollingEvery(Duration.ofMillis(500))
+                    .withTimeout(Duration.ofSeconds(timeout))
+                    .until(new Function<TestObject, Boolean>() {
+                        @Override
+                        public Boolean apply(TestObject testObj) {
+                            try {
+                                // Set timeout to 1 second to ensure that the `findElementsByLocatorStrategy` method in MobileCommonHelper class
+                                // runs at least once with the minimum timeout.
+                                // Note: Do not set the timeout to 0, as the `checkTimeout` method in the `KeywordHelper` class
+                                // will reset it to the default value (30 seconds) if the timeout is less than or equal to zero.
+                                WebElement element = findElement(testObj, 1)
+                                if (element == null) {
+                                    return true
+                                }
+                            } catch (NoSuchElementException e) {
+                                return true
+                            }
+
+                            return false
+                        }
+                    })
+            } catch (TimeoutException e) {
+                // timeOut, do nothing
+            }
+
+            if (elementNotFound) {
@@ -47,1 +81,0 @@
-                return true
@@ -50,1 +83,0 @@
-                return false
@@ -52,0 +84,2 @@
+
+            return elementNotFound
@@ -54,1 +88,0 @@
-

As far as I see the source, it seems that the Mobile.waitForElementNotPresent keyword of v10.3.0 and newer is doing some “wait”.

But I am not sure how the keyword actually works. I can not run the keyword as I don’t have any Mobile project.