Katalon can't click dropdown items because the menu closes too fast

I’m trying to automate a test case where I need to hover over a main navigation menu (like “Products”), wait for the dropdown list to appear, and then click on a sub-menu item (like “Cloud Hosting”).

When I do this manually, it works perfectly fine. But when I run my Katalon test, it fails. I used the Web Recorder to capture the steps, and it generated a WebUI.mouseOver on the main menu, followed by a WebUI.click on the sub-menu item.

When the script runs:

  1. The mouse hovers over the main menu.

  2. The dropdown opens for a split second.

  3. As soon as Katalon tries to move to the next step, the dropdown disappears, and I get an ElementNotVisibleException or StepFailedException saying the object cannot be found.

I tried adding a WebUI.delay(3) right after the hover to give it time, but the moment the delay starts, the menu closes anyway. I also tried WebUI.waitForElementVisible, but that didn’t help either because the menu doesn’t stay open long enough for the click to register. It feels like Katalon is moving the “virtual mouse” away too fast, causing the web page to think the user stopped hovering.

How do I make Katalon hold the hover open or click the sub-element before it vanishes?

Hover menus close because the cursor leaves the trigger too soon—use a hover-specific action and click the submenu immediately.

Reliable approach

WebUI.mouseOver(findTestObject('Page/Menu_Products'))
WebUI.waitForElementVisible(findTestObject('Page/Submenu_CloudHosting'), 5)
WebUI.click(findTestObject('Page/Submenu_CloudHosting'))

If the menu still collapses

  • Click instead of hover if the menu opens on click in the app.
  • Use a relative XPath for the submenu inside the menu container, not a globally captured object.
  • If your app is React/JS-driven, add a short explicit wait for the submenu to become clickable before clicking, rather than a fixed delay.

Better fallback

If hover is unstable in your app, a custom keyword that re-hovers and clicks in one flow is safer than separate recorded steps:

WebUI.mouseOver(mainMenu)
WebUI.waitForElementClickable(subMenu, 5)
WebUI.click(subMenu)

This keeps the submenu targeted while it is still open

Many web applications use JavaScript (onmouseleave events) or strict CSS :hover states. When Katalon finishes the WebUI.mouseOver action, it prepares to execute the next command. During that microsecond transition, the browser often registers that the cursor has “left” the element, triggering the menu to close immediately before the WebUI.click command can locate and target the sub-menu item.

The Solution

To resolve this reliably, we need to bypass the native mouse-move sequence or force the hover state to persist. We can achieve this using two reliable methods:

  1. The Safe Approach (Built-in Keywords): Use WebUI.clickOffset or explicit WebUI.waitForElementPresent loops.

  2. The Robust Architect Approach (JavaScript/Custom Keyword): Use JavaScript via Katalon’s WebUI.executeJavaScript to dispatch a native mouse hover event directly to the browser DOM, or trigger the click directly on the hidden element if it’s already in the DOM structure.

Custom Keyword Solution

Instead of relying on unstable native mouse movements for every dropdown, we can create a Custom Keyword that uses JavaScript to trigger a hover event, waits for the element to be clickable, and then executes the click smoothly.

Step 1: Create the Custom Keyword

Create a new Keyword package (e.g., com.helper.menu) and paste the following code:

Groovy

package com.helper.menu

import com.kms.katalon.core.annotation.Keyword
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.testobject.TestObject
import org.openqa.selenium.WebElement
import com.kms.katalon.core.webui.common.WebUiCommonHelper

public class MenuHoverHelper {

	/**
	 * Hovers over a parent menu using JavaScript and securely clicks the child sub-menu item.
	 * * @param parentMenu The TestObject of the main navigation link/button
	 * @param childItem The TestObject of the hidden/dropdown sub-menu item
	 */
	@Keyword
	def hoverAndClickSubMenu(TestObject parentMenu, TestObject childItem) {
		// Find the elements safely
		WebElement parentElement = WebUiCommonHelper.findWebElement(parentMenu, 10)
		
		// Use JavaScript to trigger a mouseover event that persists in the browser
		String javaScript = "var evObj = document.createEvent('MouseEvents');" +
							"evObj.initMouseEvent('mouseover', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);" +
							"arguments[0].dispatchEvent(evObj);"
		
		WebUI.executeJavaScript(javaScript, Arrays.asList(parentElement))
		
		// Wait for the sub-menu item to become interactive
		WebUI.waitForElementVisible(childItem, 5)
		WebUI.waitForElementClickable(childItem, 5)
		
		// Click the sub-menu item
		WebUI.click(childItem)
	}
}

Step 2: How to use it in your Test Case

Script View:

Groovy

// Call your custom keyword instead of standard mouseOver
CustomKeywords.'com.helper.menu.MenuHoverHelper.hoverAndClickSubMenu'(
    findTestObject('Object Repository/Main_Menu_Products'), 
    findTestObject('Object Repository/Sub_Menu_CloudHosting')
)

Manual View:

  1. Add a new step to your test case and select Custom Keyword.

  2. Select hoverAndClickSubMenu.

  3. Pass your Parent Menu object as the first argument and your Sub Menu Item object as the second argument.

This architectural approach removes the timing dependency of physical cursor simulation, making your test suites significantly faster and highly resilient against UI changes.

hi @tdenesik

The root cause is that Selenium’s mouseOver releases the virtual cursor after the action completes, so the browser fires mouseleave and the menu closes before the next step runs. A fixed delay won’t help because the cursor isn’t holding position during the wait.

The most reliable fix is to chain the hover and click into a single WebDriver Actions sequence so the browser never registers a gap between them:

import org.openqa.selenium.interactions.Actions
import com.kms.katalon.core.webui.driver.DriverFactory

WebElement parent = WebUiCommonHelper.findWebElement(findTestObject('Page/Menu_Products'), 10)
WebElement child = WebUiCommonHelper.findWebElement(findTestObject('Page/Submenu_CloudHosting'), 10)

new Actions(DriverFactory.getWebDriver())
    .moveToElement(parent)
    .pause(500)
    .click(child)
    .perform()

The short pause gives the dropdown animation time to render before the click fires, all within one atomic action. If the sub-item isn’t in the DOM until after hover, use waitForElementPresent on it first, then run the Actions chain.

wait for the element to be visible and/or clickable and then proceed with the next step

Just add some verification point before the clicking action.
Like waitforelementvisible, verifyelementpresent or any.

It will work

Whether it got resolved?

For me Delay was working fine, Unless a new release has been sent. I applied this solution where we create javascript event of mouse hover and its work fine. Big Thanks to you…

Thanks Everyone!