In Espresso is quite easy to tap on the first element of an `AdapterView`, such as a `ListView`. This can be easily done calling `DataIteraction.atPosition(0)`. Clicking on the last item though, is much more complicated. The last position is unknown to Espresso and extracting it stringing together a `findViewById()` and `AdapterView.getCount()` seems to defeat the purpose of using Espresso altogether.
Luckily there is a simple solution to this problem: let Espresso see the items in reversed order and then click on the first item. This can be accomplished with a custom `AdapterViewProtocol`.
`AdapterViewProtocol` is a simple interface that defines how Espresso interacts with `AdapterViews`. It supports four operations:
1. Get all data items in the adapter
2. Given a child view, return the corresponding data item
3. Given a data item, ask whether it is displayed by some child view
4. Force a data item to be displayed by a child view
For our use-case we just need to get the complete dataset and reverse it, then it can be used like this:
onData(instanceOf(MyAdapterItem.class)) .atPosition(0) .usingAdapterViewProtocol(new ReverseProtocol()) .perform(click());
Here comes the code for the protocol. Note that the standard protocol is a private class so it can’t be extended, so we delegate to it:
public class ReverseProdocol implements AdapterViewProtocol { private final AdapterViewProtocol delegate = standardProtocol(); @Override public Iterable getDataInAdapterView(AdapterView<? extends Adapter> av) { LinkedList result = new LinkedList<>(); for (AdaptedData data : delegate.getDataInAdapterView(av)) { result.addFirst(data); } return result; } @Override public Optional getDataRenderedByView(AdapterView<? extends Adapter> av, View v) { return delegate.getDataRenderedByView(av, v); } // Similarly delegate to the other two methods // ... }