package com.jakewharton.rxbinding2.support.v4.view; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.support.test.InstrumentationRegistry; import android.support.test.annotation.UiThreadTest; import android.support.test.rule.UiThreadTestRule; import android.support.test.runner.AndroidJUnit4; import android.view.ActionProvider; import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.SubMenu; import android.view.View; import com.jakewharton.rxbinding2.RecordingObserver; import com.jakewharton.rxbinding2.view.MenuItemActionViewCollapseEvent; import com.jakewharton.rxbinding2.view.MenuItemActionViewEvent; import com.jakewharton.rxbinding2.view.MenuItemActionViewExpandEvent; import io.reactivex.functions.Predicate; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.assertEquals; @RunWith(AndroidJUnit4.class) public final class RxMenuItemCompatTest { @Rule public final UiThreadTestRule uiThread = new UiThreadTestRule(); private final Context context = InstrumentationRegistry.getContext(); private final TestMenuItem menuItem = new TestMenuItem(context); @Test @UiThreadTest public void actionViewEvents() { RecordingObserver<MenuItemActionViewEvent> o = new RecordingObserver<>(); RxMenuItemCompat.actionViewEvents(menuItem).subscribe(o); o.assertNoMoreEvents(); // No initial value. menuItem.expandActionView(); assertEquals(MenuItemActionViewExpandEvent.create(menuItem), o.takeNext()); menuItem.collapseActionView(); assertEquals(MenuItemActionViewCollapseEvent.create(menuItem), o.takeNext()); o.dispose(); menuItem.performClick(); o.assertNoMoreEvents(); } @Test @UiThreadTest public void actionViewEventsAvoidHandling() { Predicate<MenuItemActionViewEvent> handled = new Predicate<MenuItemActionViewEvent>() { @Override public boolean test(MenuItemActionViewEvent menuItem) { return false; } }; RecordingObserver<MenuItemActionViewEvent> o = new RecordingObserver<>(); RxMenuItemCompat.actionViewEvents(menuItem, handled).subscribe(o); o.assertNoMoreEvents(); // No initial value. menuItem.expandActionView(); assertEquals(false, menuItem.isActionViewExpanded()); // Should be prevented by handler o.assertNoMoreEvents(); o.dispose(); menuItem.performClick(); o.assertNoMoreEvents(); } // There is no accessible default implementation of MenuItem, so we have to create one private static final class TestMenuItem implements MenuItem { private final Context context; private int itemId; private int groupId; private int order; private CharSequence title; private CharSequence titleCondensed; private Drawable icon; private Intent intent; private char numericChar; private char alphaChar; private boolean checkable; private boolean checked; private boolean visible; private boolean enabled; private OnMenuItemClickListener menuItemClickListener; private int actionEnum; private View actionView; private ActionProvider actionProvider; private boolean isActionViewExpanded; private OnActionExpandListener actionExpandListener; public TestMenuItem(Context context) { this.context = context; } public void performClick() { if (menuItemClickListener != null) { menuItemClickListener.onMenuItemClick(this); } } @Override public int getItemId() { return itemId; } @Override public int getGroupId() { return groupId; } @Override public int getOrder() { return order; } @Override public MenuItem setTitle(CharSequence title) { this.title = title; return this; } @Override public MenuItem setTitle(int title) { this.title = context.getText(title); return this; } @Override public CharSequence getTitle() { return title; } @Override public MenuItem setTitleCondensed(CharSequence title) { this.titleCondensed = title; return this; } @Override public CharSequence getTitleCondensed() { return titleCondensed; } @Override public MenuItem setIcon(Drawable icon) { this.icon = icon; return this; } @Override public MenuItem setIcon(int iconRes) { this.icon = context.getResources().getDrawable(iconRes); return this; } @Override public Drawable getIcon() { return icon; } @Override public MenuItem setIntent(Intent intent) { this.intent = intent; return this; } @Override public Intent getIntent() { return intent; } @Override public MenuItem setShortcut(char numericChar, char alphaChar) { this.numericChar = numericChar; this.alphaChar = alphaChar; return this; } @Override public MenuItem setNumericShortcut(char numericChar) { this.numericChar = numericChar; return this; } @Override public char getNumericShortcut() { return numericChar; } @Override public MenuItem setAlphabeticShortcut(char alphaChar) { this.alphaChar = alphaChar; return this; } @Override public char getAlphabeticShortcut() { return alphaChar; } @Override public MenuItem setCheckable(boolean checkable) { this.checkable = checkable; return this; } @Override public boolean isCheckable() { return checkable; } @Override public MenuItem setChecked(boolean checked) { if (checkable) { this.checked = checked; } return this; } @Override public boolean isChecked() { return checked; } @Override public MenuItem setVisible(boolean visible) { this.visible = visible; return this; } @Override public boolean isVisible() { return visible; } @Override public MenuItem setEnabled(boolean enabled) { this.enabled = enabled; return this; } @Override public boolean isEnabled() { return enabled; } @Override public boolean hasSubMenu() { return false; } @Override public SubMenu getSubMenu() { return null; } @Override public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) { this.menuItemClickListener = menuItemClickListener; return this; } @Override public ContextMenu.ContextMenuInfo getMenuInfo() { return null; } @Override public void setShowAsAction(int actionEnum) { this.actionEnum = actionEnum; } @Override public MenuItem setShowAsActionFlags(int actionEnum) { this.actionEnum = actionEnum; return this; } @Override public MenuItem setActionView(View view) { this.actionView = view; return this; } @Override public MenuItem setActionView(int resId) { this.actionView = LayoutInflater.from(context).inflate(resId, null); return this; } @Override public View getActionView() { return actionView; } @Override public MenuItem setActionProvider(ActionProvider actionProvider) { this.actionProvider = actionProvider; return this; } @Override public ActionProvider getActionProvider() { return actionProvider; } @Override public boolean expandActionView() { if (isActionViewExpanded) { return false; } if (actionExpandListener != null && !actionExpandListener.onMenuItemActionExpand(this)) { return false; } isActionViewExpanded = true; return true; } @Override public boolean collapseActionView() { if (!isActionViewExpanded) { return false; } if (actionExpandListener != null && !actionExpandListener.onMenuItemActionCollapse(this)) { return false; } isActionViewExpanded = false; return true; } @Override public boolean isActionViewExpanded() { return isActionViewExpanded; } @Override public MenuItem setOnActionExpandListener(OnActionExpandListener listener) { this.actionExpandListener = listener; return this; } } }