package com.mindbodyonline.ironhide.Infrastructure.IronhideViews; import android.view.View; import com.mindbodyonline.ironhide.PageObjects.PageObject; import org.hamcrest.Matcher; import static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withText; import static com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers.hasIndex; import static com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers.instanceOf; import static org.hamcrest.Matchers.allOf; /** * Simple element that allows to interact with ListViews that have children added dynamically. * Enables access to ListItems inside a dynamic ListView that does not use an adapter. * This element is rarely used, as these types of ListViews are considered bad practice * * @param <T> The model the current element will return when interacted with */ public class DynamicListAdapter<T extends PageObject> { private final Class<T> type; private final Matcher<View> childMatcher; /** * A generically typed DynamicListAdapter with selector: * {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)} * @param itemType the class type to use for {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)} */ public DynamicListAdapter(Class<T> type, Class itemType) { this(type, instanceOf(itemType)); } /** * A generically typed DynamicListAdapter with selector: * {@link org.hamcrest.Matchers#allOf(Iterable)} * with sub-matchers: * {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)}, * and {@link android.support.test.espresso.matcher.ViewMatchers#isDescendantOfA(org.hamcrest.Matcher)}, * the second of which also has sub-matcher: * {@link android.support.test.espresso.matcher.ViewMatchers#withId(int)}. * @param itemType the class type to use for {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)} * @param parentId the id to use for {@link android.support.test.espresso.matcher.ViewMatchers#withId(int)} */ @SuppressWarnings("unchecked") public DynamicListAdapter(Class<T> type, Class itemType, int parentId) { this(type, allOf(instanceOf(itemType), isDescendantOfA(withId(parentId)))); } /** * A generically typed DynamicListAdapter with selector: * {@link org.hamcrest.Matchers#allOf(Iterable)} * with sub-matchers: * {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)}, * and {@link android.support.test.espresso.matcher.ViewMatchers#isDescendantOfA(org.hamcrest.Matcher)}, * the second of which also has sub-matcher: * {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)}. * @param itemType the class type to use for the first usage of {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)} * @param parentClass the class to use for the second usage of {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)} */ @SuppressWarnings("unchecked") public DynamicListAdapter(Class<T> type, Class itemType, Class parentClass) { this(type, allOf(instanceOf(itemType), isDescendantOfA( instanceOf(parentClass) ))); } /** * A generically typed DynamicListAdapter with selector: * {@link org.hamcrest.Matchers#allOf(Iterable)} * with sub-matchers: * {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)}, * and {@link android.support.test.espresso.matcher.ViewMatchers#isDescendantOfA(org.hamcrest.Matcher)}, * the second of which also has sub-matchers: * {@link android.support.test.espresso.matcher.ViewMatchers#withId(int)} and * {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)}. * @param itemType the class type to use for the first usage of {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)} * @param parentId the id to use for {@link android.support.test.espresso.matcher.ViewMatchers#withId(int)} * @param parentClass the class to use for the second usage of {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#instanceOf(Class)} */ @SuppressWarnings("unchecked") public DynamicListAdapter(Class<T> type, Class itemType, int parentId, Class parentClass) { this(type, allOf(instanceOf(itemType), isDescendantOfA(allOf( withId(parentId), instanceOf(parentClass) )))); } /** * Instantiates a {@link android.support.test.espresso.ViewInteraction} and retains type and matcher for later access. * @param type the class of the generic type * @param childMatcher the {@link org.hamcrest.Matcher} to select the {@link android.widget.AdapterView} */ public DynamicListAdapter(Class<T> type, Matcher<View> childMatcher) { this.type = type; this.childMatcher = childMatcher; } /** @see BaseView#goesTo(Class) */ public <E extends PageObject> DynamicListAdapter<E> goesTo(Class<E> type) { return new DynamicListAdapter<>(type, childMatcher); } /** * Creates a new {@link Clickable} for the matcher of the child and {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#hasIndex(int)} * @param index the index for {@link com.mindbodyonline.ironhide.Infrastructure.Extensions.BaseViewMatchers#hasIndex(int)} * @return the Clickable created */ public Clickable<T> getItemAt(int index) { return getItemMatching(hasIndex(index)); } /** * Creates a new {@link Clickable} for the matcher of the child and {@link android.support.test.espresso.matcher.ViewMatchers#withText(int)} * @param text the String to use for {@link android.support.test.espresso.matcher.ViewMatchers#withText(int)} * @return the Clickable created */ public Clickable<T> getItemFromText(String text) { return getItemMatching(withText(text)); } /** * Creates a new {@link Clickable} for the matcher of the child and itemMatcher * @param itemMatcher the {@link org.hamcrest.Matcher} to append to the child matcher * @return the Clickable created */ @SuppressWarnings("unchecked") public Clickable<T> getItemMatching(Matcher<View> itemMatcher) { return new Clickable<>(type, allOf(isDisplayed(), childMatcher, itemMatcher)); } }