The only keyword which can interact with my IOS elements is 'Double Tap'

Operating System

MacOS Big Sur 11.4

Katalon Studio Version

8.4.0

Environment (for Mobile testing):

  • Appium version
    1.22.3

  • Mobile platform/version under test: (for example: iOS 11 or Android 7)
    iOS 15.2

  • Real device or emulator/simulator: (for example: iPhone 6s real or Nexus 6 simulator)
    iPad 9th Generation Simulator

  • Xcode version (for iOS): (for example: Xcode 8 or Xcode 11)
    13.2.1

Steps to reproduce:

Problem #1

Using the ‘Start Existing Application’ keyword start your IOS app.
This will unforutnately restart the application on every test run (which is annoying as it means I need to run a log in script before every test).
The only way for me to interact with elements, specifically tap on them, is by using the ‘Double Tap’ keyword. This does not act like a Double Tap within my application and has thus far only ever tapped on the element at hand once (which is what I want as an alternative to not being able to us 'Tap).
Even when using the recorder and being 100% confident Katalon knows about the object I’m pointing at, the ‘Tap’ command will ‘pass’ but never actually taps the element!

Problem #2
To combat the issue experienced above regarding the app restarting on each test run, I decided to instead use the ‘Start Application’ keyword and set the uninstallafterclose param to false. This fixed that issue.
The problems arose when I soon found whilst I am still unable to use the ‘Tap’ keyword, my workaround of using ‘Double Tap’ now actually does double tap! (This is not what I want as it generates unexpected results.)

Final question to solve!

Essentially, I’d like to know how to:

  1. Start my application without the need for a restart on each test case execution WHILST simultaneously being able to use the ‘Tap’ keyword OR at least being able to use the work around of ‘Double Tap.’

Please also provide your test scripts if possible.

import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import static com.kms.katalon.core.testobject.ObjectRepository.findWindowsObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords as CucumberKW
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testng.keyword.TestNGBuiltinKeywords as TestNGKW
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.windows.keyword.WindowsBuiltinKeywords as Windows
import internal.GlobalVariable as GlobalVariable
import org.openqa.selenium.Keys as Keys
import com.kms.katalon.core.util.KeywordUtil as KeywordUtil

Mobile.startApplication(‘/Users/KATALON/tasea.app’, false)

try {

'Navigate to trinoor module'
Mobile.doubleTap(findTestObject('IOS_OBJECTS/002_STAPLE_OBJECTS/001_trinoorModule'), 0, FailureHandling.STOP_ON_FAILURE)

'Navigate to Math subapp'
Mobile.doubleTap(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/001_mathSubApp'), 0, FailureHandling.STOP_ON_FAILURE)

'The following \'Verify Element Exist\' steps can only pass if the value of each object has a predefined and expected attribute value '
Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/002_result_44'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/003_result_7'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/004_result_18'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/005_result_3'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/006_result_440009'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/007_result_70003'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/008_result_180045'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/009_result_29999'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/010_result_infinity'), 0)

'Scroll to new region'
Mobile.scrollToText('Logic', FailureHandling.STOP_ON_FAILURE)

// Mobile.scrollToText('Logic', FailureHandling.STOP_ON_FAILURE)
'Tap the logic button'
Mobile.tap(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/011_logic_button'), 0)

'Verify a false result is generated'
Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/012_false_result'), 0)

'Get to text input'
Mobile.doubleTap(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/012_compareTextInput'), 0)

'Change the text to ensure a positive result is generated'
Mobile.setText(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/012_compareTextInput'), 'compare_text_1', 0)

'Tap logic button'
Mobile.doubleTap(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/011_logic_button'), 0)

'Verify true result'
Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/013_true_result'), 0)

'Scroll to next region'
Mobile.scrollToText('Conversions', FailureHandling.STOP_ON_FAILURE)

'The following \'Verify Element Exist\' steps can only pass if the value of each object has a predefined and expected attribute value '
Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/014_result_508cm'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/015_result_error'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/016_result_679999999fahr'), 0)

Mobile.verifyElementExist(findTestObject('IOS_OBJECTS/003_TRINOOR_MODULE/001_MATH/017_result_25ms'), 0)

'Navigate back home'
Mobile.doubleTap(findTestObject('IOS_OBJECTS/002_STAPLE_OBJECTS/002_homeButton'), 0)

}
catch (Exception ex) {
KeywordUtil.markFailed('Test failed due to: ’ + ex)

Mobile.doubleTap(findTestObject('IOS_OBJECTS/002_STAPLE_OBJECTS/002_homeButton'), 0)

}

@josh.thompson, can you provide the application for us to test? Also, are you testing on a real device or a simulation?

1 Like

Hi Chen, I have just spoken with my development manager and I am able to provide you with the application. Do you have a preference on how you’d like me to share it?

I was testing on a simulator, I’m currently unable to test on a real device.

@josh.thompson, you can provide the application on the Google Drive folder here.

Hi Chen, I have uploaded the .app file! You won’t be able to log in, but if you are able to even just tap on elements that would solve my problem.
Thank you in advance.

@josh.thompson, can you send the complete app as .ipa file?

Hi Chen, unfortunately I cannot. This problem has put a complete hold on IOS testing, so any possible fixes would be greatly appreciated.

You can try using Mobile.tapAtPosition(). To get your position (x, y), you need to go to the Object Properties and check the x and y values. You can check the doc for more info on the keyword here.

Yes I was able to tap at position but as I’m testing on multiple devices tapping at a position is not an ideal way to test for me

Currently, Mobile.tapAtPosition() is the only solution we can think of, so if it works for you, then you should continue with it for now. You can always wait for other users to suggest better ideas.

For anyone interested, this is how I navigated around the problem

class Tapper {
	int x;
	int y;

	/**
	 * Find test object and tap it based on attribute values x and y.	
	 * @param String Katalon test object
	 */
	@Keyword
	def tapObject(String to) {
		KeywordUtil.logInfo("Attempting to finding x and y coordinates of test object: " + to);
		x = Integer.parseInt(Mobile.getAttribute(findTestObject(to), 'x', 30));
		y = Integer.parseInt(Mobile.getAttribute(findTestObject(to), 'y', 30));
		KeywordUtil.logInfo('Found test object coordinates: '+x+', '+y);
		Mobile.tapAtPosition(x * 2, y * 2);
	}
}