The issue where a tap action passes but doesn’t execute on iOS (while working on Android) is usually caused by XCUITest framework limitations or element visibility misdetection. Here’s how to fix it:
1. Use Native iOS Tap via Mobile.callTestCase()
Bypass Katalon’s tap and use iOS native XCUITest code:
groovy
Mobile.callTestCase('classpath://iOS_Helpers/ios_tap_button', [
('label'): 'Lanjut',
('timeout'): 10
])
Create a iOS_Helpers/ios_tap_button
test case with:
groovy
// iOS-specific tap using XCUITest
@Keyword
def tapIOSButton(String label, int timeout) {
MobileDriver driver = MobileDriverFactory.getDriver()
WebElement button = driver.findElementByXPath("//XCUIElementTypeButton[@name='${label}']")
button.click()
}
2. Adjust Desired Capabilities for iOS
Modify your iOS capabilities in Mobile Settings
:
json
{
"platformName": "iOS",
"automationName": "XCUITest",
"nativeEvents": true, // Critical for iOS taps
"waitForQuiescence": false // Disable to prevent premature checks
}
3. Use Absolute Coordinates with Offsets
If the element is offscreen or in a scroll view:
groovy
// Get element position and adjust for safe tap
TestObject buttonObj = findTestObject('Dynamic.XCUIElement.TypeButton', [('label') : 'Lanjut'])
MobileElement element = Mobile.getElement(buttonObj)
int x = element.getCenter().x
int y = element.getCenter().y - 50 // Adjust for navigation bars
Mobile.tapAtPosition(x, y)
4. Disable Wait for Element
iOS sometimes falsely reports element visibility. Force tap:
groovy
MobileElement element = Mobile.getElement(buttonObj)
element.click() // Direct WebElement click
5. Handle Nested Elements
For buttons inside containers (e.g., XCUIElementTypeOther
), use XPath:
groovy
TestObject buttonObj = findTestObject('Dynamic.XCUIElement.TypeButton', [('label') : 'Lanjut'])
MobileElement element = Mobile.getElement(buttonObj)
Mobile.swipe(0, 0, 0, 0) // Workaround for nested focus
element.click()
6. Update Katalon & Dependencies
Ensure you’re using:
- Katalon 10.2.0+ (fixed XCUITest issues)
- Appium 2.0+
- Xcode 15.4+ with latest iOS SDK
Full Working Script
groovy
'User Accept the Terms and Conditions'
TestObject buttonObj = findTestObject('Dynamic.XCUIElement.TypeButton', [('label') : 'Lanjut'])
// Wait using custom handler
Mobile.waitForElementPresent(buttonObj, 10)
Mobile.swipe(0, 0, 0, 0) // Force UI refresh
// Get element and tap via native method
MobileElement element = Mobile.getElement(buttonObj)
int x = element.getCenter().x
int y = element.getCenter().y
// Compensate for iOS status bar/nav offsets
Mobile.tapAtPosition(x, y - 100)
// Verify tap succeeded
Mobile.waitForElementPresent(findTestObject('NextScreen'), 5)
Why This Works
- Native Events: Bypass Katalon’s abstraction layer.
- Coordinate Adjustments: Account for iOS-specific UI hierarchies.
- XCUITest Optimization: Direct framework interaction reduces false positives.