Basically I'm testing an iOS app on the simulator, wrote in react-native
, using appium with XCUITest
and webriver
.
I noticed I couldn't reach through locators "next" and "previous" button, located on a calendar (used to choose the month), that is placed on a modal.
So I decided to try to tap it through the tap by coordinates strategy: I retrieved the coords with appium inspector, and I've tried the followings:
settings in the config file (notice, if can make any difference, I've set 'appium:nativeWebTap': true
:
capabilities = [
{
// the path for appium server
path: '/wd/hub',
// The defaults you need to have in your config
platformName: 'iOS',
maxInstances: 1,
// For W3C the appium capabilities need to have an extension prefix
// This is `appium:` for all Appium Capabilities which can be found here
// http://appium.io/docs/en/writing-running-appium/caps/
'appium:deviceName': 'iPhone 8',
'appium:platformVersion': '15.5',
'appium:orientation': 'PORTRAIT',
// `automationName` will be mandatory, see
// https://github.com/appium/appium/releases/tag/v1.13.0
'appium:automationName': 'XCUITest',
// The path to the app
'appium:app': join(process.cwd(), './app_test/myApp.app'),
// Read the reset strategies very well, they differ per platform, see
// http://appium.io/docs/en/writing-running-appium/other/reset-strategies/
'appium:noReset': false,
// How long (in seconds) Appium will wait for a new command from the client before assuming the client quit and ending the session
// default: 240
'appium:newCommandTimeout': 500,
'appium:autoGrantPermissions': true,
'appium:autoAcceptAlerts': true,
'appium:nativeWebTap': true,
// make process headless
'appium:isHeadless': false,
'appium:settings[snapshotMaxDepth]': 60
}
my test file:
describe('Testing', () => {
it('Test tap', async () => {
//TEST:
await driver.setTimeouts(30000)
// first try
await driver.touchAction({ action: 'tap', x: 323, y: 225 })
// second try
await driver.execute('mobile: tap', { x: 323, y: 225 })
// just to avoid instant disappearing
await browser.pause(10000)
})
})
None of the two worked: I mean that no tap happens. I also noticed that while an iphone8 (and so the simulator, I think) has a 750x1334 resolution, the maximum x and y coordinates in the appium inspector are 375x666.
So I just did a proportion
323:375=x:750 //x=646
225:666=x:1334. //y=451
and i used 646, 451
as cooords, but didn't work.
So, my idea is that the code I wrote simply does not tap at all.
What I'm doing wrong? what's the trick to do a simple TAP with coordinates in appium?
Solved.
TL:DR; => go to the last block of code, at the bottom of the answer.
I tried uncountable times, uncountable options, due to the lack of documentation in webdriverIO documentation and appium documentation.
So, after trying:
// not working with iphone simulator and XCUITest
await browser.touchAction({
action: 'tap',
x: 295,
y: 200
})
// not working with iphone simulator and XCUITest
await driver.execute('mobile: tap', { x: 600, y: 400 })
// not working with iphone simulator and XCUITest
await elem.touchAction({ action: 'click', x: 320, y: 290 })
// not working with iphone simulator and XCUITest
await driver.touchAction({ action: 'tap', x: 295, y: 200 })
// not working with iphone simulator and XCUITest
await driver.touchAction({ actions: [{ action: 'tap', options: { x: 295, y: 200 } }] })
and at least another dozens of commands, I went to the webdriverio github.
I found some interesting things, for example here I found the actions list for touchAction command:
export type ActionTypes = 'press' | 'longPress' | 'tap' | 'moveTo' | 'wait' | 'release';
'release' is a bit different from the others, and must be used like the last example of this page.
I've also found the only current working way (october, 2022) to tap with JS:
await driver.touchAction([{ action: 'tap', x: 0, y: 0, element: elementName }])
This function takes in input:
all the other examples listed here did not work for me.
I solved my issue retrieving an element under the <
and >
calendar buttons and adding or subtracting a bunch of pixel just looking at the screen.
REMEMBER: x and y values used in appium inspector DO NOT correspond to pixels.
So, for example, to tap on the <
calendar button shown here:
i had to
// retrieve sunday block
// there's no Id on this calendar element
const sunday = await $(
'-ios class chain:**/XCUIElementTypeOther[`name == "native.calendar.DAY_NAMES"`]/XCUIElementTypeStaticText[1]'
)
// just looked at the above screen I thought the left arrow is more or less 20px above,
//so from the center of the sunday element:
await driver.touchAction([{ action: 'tap', x: 20, y: -20, element: sunday }])