After we added our Android elements and defined them in the application, let's now try to add the iOS locators from our iOS application.
I already started the inspection session with my to-do application, and here we will do the same - find the button to be able to click to add new tasks.
We have the Accessibility ID, so we can copy this one.
The question here is - can we create a new element for this iOS element, or can we add the annotation with the same one?
The real case is that we can add the annotation for iOS with the same WebElement or MobileElement that we added.
So, I can open the TasksListPage
on the element addTaskBtn
, I already have an AndroidFindBy
annotation, and I will add another one for iOS.
The annotation is @iOSXCUITFindBy()
.
We need to import this, and the import class comes from pagefactory
.
Then, what shall I add here?
We have id
, iOSClassChain
, accessibility
, xpath
, iOSNsPredicate
, priority
, className
and tagName
.
In our case, if we return back to the session, we have the Accessibility ID, so we can copy this one, and then we can select accessibility
which is "plus.circle" and add this button.
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.pagefactory.AndroidFindBy;
import io.appium.java_client.pagefactory.iOSXCUITFindBy;
public class TasksListPage extends PageBase {
public TasksListPage(AppiumDriver appiumDriver) {
super(appiumDriver);
}
@AndroidFindBy(id = "fab")
@iOSXCUITFindBy(accessibility = "plus.circle")
MobileElement addTaskBtn;
public void clickAddTaskBtn() {
click(addTaskBtn);
}
}
So here, one element can be working with Android with this ID, and with iOS with this accessibility ID.
The driver differentiates between which ID or which accessibility ID or which locator strategy that we can pick up from the PageObject.
So this is for the addTaskBtn
and we will do the same with the CreateTaskPage
class.
Here we have 3 elements and then in the inspection session, we just click on the "+" button.
Here we have a title, we have a description, and we have a save button.
We can click again here in the Title - here we have the "-ios predicate string", "-ios class chain", and we don't have Accessibility ID so maybe we can use one of these two elements.
For example, for this one we can use the predicate ID - we have the value == "Title".
So, we can go to our element with the task name and add one for @iOSXCUITFindBy
- we need to import this - and then we can pass in iOSNsPredicate = "value == 'Title'"
.
The value is value == "Title"
but we have two strings or double quotes, so we need to switch one to be single quote to be a valid string.
So, this is different - we will use this one for the first time, but let's try and if it's not working we can try the chain one.
This is the first one, and then we need to add the description and the save button.
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.pagefactory.AndroidFindBy;
import io.appium.java_client.pagefactory.iOSXCUITFindBy;
public class CreateTaskPage extends PageBase {
public CreateTaskPage(AppiumDriver appiumDriver) {
super(appiumDriver);
}
@AndroidFindBy(id = "editTextTitre")
@iOSXCUITFindBy(iOSNsPredicate = "value == 'Title'")
MobileElement taskNameTxt;
@AndroidFindBy(id = "editTextNote")
MobileElement taskDescTxt;
@AndroidFindBy(id = "action_save")
MobileElement saveBtn;
public void enterTaskName(String taskName) {
clear(taskNameTxt);
sendText(taskNameTxt, taskName);
}
public void enterTaskDesc(String descText) {
clear(taskDescTxt);
sendText(taskDescTxt, descText);
}
public void clickSaveBtn() {
click(saveBtn);
}
}
Let's go to the description, and for this one, we will use the same thing.
We will add @iOSXCUITFindBy()
and pass iOSNsPredicate = "value == 'Description'"
and again we switch to a single quote to be a correct string.
Then for the save button, we need to find this one in the inspector.
Here we have "Create Task" and then here we have the save button.
We have the Accessibility ID - we can use the Predicate or Class Chain, but here we already have this Accessibility ID.
With the save button, we can add @iOSXCUITFindBy()
, and then we can pass accessibility = "Save"
.
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.pagefactory.AndroidFindBy;
import io.appium.java_client.pagefactory.iOSXCUITFindBy;
public class CreateTaskPage extends PageBase {
public CreateTaskPage(AppiumDriver appiumDriver) {
super(appiumDriver);
}
@AndroidFindBy(id = "editTextTitre")
@iOSXCUITFindBy(iOSNsPredicate = "value == 'Title'")
MobileElement taskNameTxt;
@AndroidFindBy(id = "editTextNote")
@iOSXCUITFindBy(iOSNsPredicate = "value == 'Description'")
MobileElement taskDescTxt;
@AndroidFindBy(id = "action_save")
@iOSXCUITFindBy(accessibility = "Save")
MobileElement saveBtn;
public void enterTaskName(String taskName) {
clear(taskNameTxt);
sendText(taskNameTxt, taskName);
}
public void enterTaskDesc(String descText) {
clear(taskDescTxt);
sendText(taskDescTxt, descText);
}
public void clickSaveBtn() {
click(saveBtn);
}
}
Now, our page objects are ready for both Android and iOS.
So in the next video, we'll start using this page object in our test classes, but first, we will start creating our test base, and then we really start creating our test class.
Quiz
The quiz for this chapter can be found in Chapter 7.5