package com.mindbodyonline.ironhide.Infrastructure.IronhideViews;
import android.support.test.espresso.DataInteraction;
import android.support.test.espresso.Root;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.ViewAssertion;
import android.support.test.espresso.assertion.ViewAssertions;
import android.support.test.espresso.matcher.ViewMatchers;
import android.view.View;
import com.mindbodyonline.ironhide.PageObjects.PageObject;
import org.hamcrest.Matcher;
import static android.support.test.espresso.Espresso.onData;
import static org.hamcrest.Matchers.anything;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
/**
* Complex element that allows to interact with an {@link android.widget.AdapterView} that uses an {@link android.widget.Adapter}.
* Gives access to individual {@link com.mindbodyonline.ironhide.Infrastructure.IronhideViews.ListItem}s inside an {@link android.widget.AdapterView}.
* Only use this element when dealing with an {@link android.widget.AdapterView} that has an {@link android.widget.Adapter}
*
* @param <T> The model the current element will return when interacted with
*/
public class ListAdapter<T extends PageObject> extends BaseView<T> {
private DataInteraction adapter;
/**
* Retains type and adapter for use later on.
* @param type the class of the generic type
* @param adapter the {@link android.support.test.espresso.DataInteraction} for the {@link android.widget.AdapterView} this represents
*/
@SuppressWarnings("unchecked")
private ListAdapter(Class<T> type, DataInteraction adapter) {
super(type, (Matcher) anything());
this.adapter = adapter;
}
/**
* A generically typed ListAdapter.
* Instantiates a {@link android.support.test.espresso.DataInteraction}
* @param adapterGeneric the class of the objects that make up the list items in the list view.
*/
@SuppressWarnings("unchecked")
public ListAdapter(Class<T> type, Class adapterGeneric) {
super(type, (Matcher) anything());
adapter = onData(is(instanceOf(adapterGeneric)));
}
/**
* A generically typed ListAdapter.
* Instantiates a {@link android.support.test.espresso.DataInteraction}
* @param adapterGeneric the class of the objects that make up the list items in the list view.
* @param id the id of the {@link android.widget.AdapterView}
*/
@SuppressWarnings("unchecked")
public ListAdapter(Class<T> type, Class adapterGeneric, int id) {
this(type, adapterGeneric, ViewMatchers.withId(id));
}
/**
* A generically typed ListAdapter.
* Instantiates a {@link android.support.test.espresso.DataInteraction}
* @param adapterGeneric the class of the objects that make up the list items in the list view.
* @param selector the {@link org.hamcrest.Matcher} for the {@link android.widget.AdapterView}
*/
public ListAdapter(Class<T> type, Class adapterGeneric, Matcher<View> selector) {
super(type, selector);
adapter = onData(is(instanceOf(adapterGeneric))).inAdapterView(selector);
}
/**
* A generically typed ListAdapter.
* Instantiates a {@link android.support.test.espresso.DataInteraction}
* @param filter the {@link org.hamcrest.Matcher} for the {@link android.database.Cursor} held by the {@link android.widget.CursorAdapter}
*/
@SuppressWarnings("unchecked")
public ListAdapter(Class<T> type, Matcher<Object> filter) {
super(type, (Matcher) anything());
adapter = onData(filter);
}
/**
* A generically typed ListAdapter.
* Instantiates a {@link android.support.test.espresso.DataInteraction}
* @param filter the {@link org.hamcrest.Matcher} for the {@link android.database.Cursor} held by the {@link android.widget.CursorAdapter}
* @param selector the {@link org.hamcrest.Matcher} for the {@link android.widget.AdapterView}
*/
public ListAdapter(Class<T> type, Matcher<Object> filter, Matcher<View> selector) {
super(type, selector);
adapter = onData(filter).inAdapterView(selector);
}
/**
* Changes the destination class by returning an object of the given type
* @param type New class for Adapter to return to.
* @return New ListAdapter with return type of type.
*/
public <E extends PageObject> ListAdapter<E> goesTo(Class<E> type) {
return new ListAdapter<>(type, adapter);
}
/**
* Returns the ListItem at the given position in the List Hierarchy.
* @param index Index of the ListItem to return.
* @return The ListItem at position index.
*/
public ListItem<T> getItemAtPosition(int index) {
return new ListItem<>(type, adapter.atPosition(index)).goesTo(type);
}
/**
* Returns the ListItem at the first position in the List Hierarchy.
* @return The ListItem at the first position.
*/
public ListItem<T> getFirst() {
return new ListItem<>(type, adapter.atPosition(0)).goesTo(type);
}
/**
* Returns the {@link ListItem} matching the given {@link BaseView}
* @param toMatch the {@link BaseView} with the {@link org.hamcrest.Matcher} for the {@link android.widget.AdapterView}
*/
public ListItem<T> getItem(BaseView<?> toMatch) {
return new ListItem<>(type, adapter.onChildView(toMatch.getSelector()));
}
/**
* Actions are performed on the DataInteraction instead of the ViewInteraction
*/
/** {@inheritDoc} */
@Override
protected T performAction(ViewAction viewAction) {
adapter.perform(viewAction);
return returnGeneric();
}
/** {@inheritDoc} */
@Override
protected T checkMatches(Matcher<? super View> viewMatcher) {
return checkAssertion(ViewAssertions.matches(viewMatcher));
}
/** {@inheritDoc} */
@Override
protected T checkAssertion(ViewAssertion viewAssertion) {
adapter.check(viewAssertion);
return returnGeneric();
}
/**
* Root Matchers return ListAdapter
*/
/** {@inheritDoc} */
@Override
public ListAdapter<T> changeRoot() {
return (ListAdapter<T>) super.changeRoot();
}
/** {@inheritDoc} */
@Override
public ListAdapter<T> inRoot(Matcher<Root> rootMatcher) {
this.adapter = this.adapter.inRoot(rootMatcher);
return this;
}
/** {@inheritDoc} */
@Override
public ListAdapter<T> inDialogRoot() {
return (ListAdapter<T>) super.inDialogRoot();
}
/** {@inheritDoc} */
@Override
public ListAdapter<T> inPlatformPopup() {
return (ListAdapter<T>) super.inPlatformPopup();
}
/** {@inheritDoc} */
@Override
public ListAdapter<T> inTouchableRoot() {
return (ListAdapter<T>) super.inTouchableRoot();
}
/** {@inheritDoc} */
@Override
public ListAdapter<T> inDecorView(Matcher<View> decorViewMatcher) {
return (ListAdapter<T>) super.inDecorView(decorViewMatcher);
}
/** {@inheritDoc} */
@Override
public ListAdapter<T> inFocusableRoot() {
return (ListAdapter<T>) super.inFocusableRoot();
}
}