-
Notifications
You must be signed in to change notification settings - Fork 23
POP Tricks
Here are several tricks you can use to make defining queries easier.
Imagine you have the following method in one of your page classes:
public void SelectListItem(string itemText)
{
app.Tap(x => x.Class("ListViewItem").Text(itemText));
}
This is not correct. We should never define queries inside a method. They should all be saved as fields at the top of the class (as explained in rule #2).
However, we also don't want to define a separate query for every single list item because there may be quite a few of them and they will only differ in their text values.
We can get around these issues by defining a nested lambda expression. The outer lambda takes in the value that changes as a parameter and returns another lambda expression (the query) based on that parameter. This is how it would look:
readonly Func<string, Func<AppQuery, AppQuery>> ListItem;
// In constructor:
ListItem = itemName => x => x.Class("ListViewItem").Text(itemName);
This essentially creates a method that takes in itemName
as a parameter and returns the query x => x.Class("ListViewItem").Text(itemName)
back to the caller. You can use it like this:
app.Tap(ListItem("first item text"));
app.Tap(ListItem("second item text"));
Which is functionally the same as writing:
app.Tap(x => x.Class("ListViewItem").Text("first item text"));
app.Tap(x => x.Class("ListViewItem").Text("second item text"));
So now we can rewrite our original method to conform to the guidelines:
public void SelectListItem(string itemText)
{
app.Tap(ListItem(itemText));
}
All the methods in UITest generally take in a lambda expression that specifies the element to interact with (we often refer to this as a "query"). For example, app.Tap(x => x.Id("log-in-button"))
uses the lambda x => x.Id("log-in-button")
to define what to tap on. All queries are expected to be of type Func<AppQuery, AppQuery>
and to define them you write:
readonly Func<AppQuery, AppQuery> LogInButton;
// In constructor:
LogInButton = x => x.Id("log-in-button");
However, writing Func<AppQuery, AppQuery>
for every query can get tiresome and isn't that descriptive. We can make defining queries easier by adding the following line with our using
statements at the very top of the file:
using Query = System.Func<Xamarin.UITest.Queries.AppQuery, Xamarin.UITest.Queries.AppQuery>;
This aliases Func<AppQuery, AppQuery>
with Query
so we can rewrite the original definition like so:
readonly Query LogInButton;
// In constructor:
LogInButton = x => x.Id("log-in-button");