package com.beloo.widget.chipslayoutmanager;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.ViewInteraction;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import com.beloo.chipslayoutmanager.sample.R;
import com.beloo.chipslayoutmanager.sample.entity.ChipsEntity;
import com.beloo.chipslayoutmanager.sample.ui.ChipsFacade;
import com.beloo.chipslayoutmanager.sample.ui.LayoutManagerFactory;
import com.beloo.chipslayoutmanager.sample.ui.TestActivity;
import com.beloo.widget.chipslayoutmanager.util.InstrumentalUtil;
import com.beloo.widget.chipslayoutmanager.util.testing.ISpy;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.List;
import java.util.Locale;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static com.beloo.test.util.RecyclerViewEspressoFactory.actionDelegate;
import static com.beloo.test.util.RecyclerViewEspressoFactory.notifyItemRemovedAction;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* test for {@link TestActivity}
*/
@RunWith(AndroidJUnit4.class)
public class FewChipsColumnTest {
static {
TestActivity.isInitializeOutside = true;
}
@Rule
public ActivityTestRule<TestActivity> activityTestRule = new ActivityTestRule<>(TestActivity.class);
@Mock
ISpy spy;
@Mock
LayoutManagerFactory layoutManagerFactory;
private ChipsLayoutManager layoutManager;
private List<ChipsEntity> items;
private TestActivity activity;
@Before
public void setUp() throws Throwable {
MockitoAnnotations.initMocks(this);
activity = activityTestRule.getActivity();
layoutManager = getLayoutManager();
doReturn(layoutManager).when(layoutManagerFactory).layoutManager(any());
RecyclerView rvTest = (RecyclerView) activityTestRule.getActivity().findViewById(R.id.rvTest);
//disable all animations
rvTest.setItemAnimator(null);
//set items
ChipsFacade chipsFacade = spy(new ChipsFacade());
items = chipsFacade.getItems();
when(chipsFacade.getItems()).thenReturn(items);
TestActivity.setItemsFactory(chipsFacade);
TestActivity.setLmFactory(layoutManagerFactory);
}
protected ChipsLayoutManager getLayoutManager() {
return ChipsLayoutManager.newBuilder(activityTestRule.getActivity())
.setOrientation(ChipsLayoutManager.VERTICAL)
.build();
}
/**
* test, that {@link android.support.v7.widget.LinearLayoutManager#onLayoutChildren} isn't called infinitely
*/
@Test
public void onLayoutChildren_afterActivityStarted_onLayoutCallLimited() throws Exception {
//arrange
activity.runOnUiThread(() -> activity.initialize());
//act
//we can't wait for idle, coz in case of error it won't be achieved. So just approximate time here.
Thread.sleep(700);
//assert
verify(spy, atMost(6)).onLayoutChildren(any(RecyclerView.Recycler.class), any(RecyclerView.State.class));
}
@Test
public void wrapContent_HeightIsWrapContent_DeletedLastItemInLastRowCauseHeightToDecrease() throws Exception {
//arrange
activity.runOnUiThread(() -> activity.initialize());
final RecyclerView[] rvTest = new RecyclerView[1];
ViewInteraction recyclerView = onView(withId(R.id.rvTest)).check(matches(isDisplayed()));
ViewAction viewAction = actionDelegate(((uiController, view) -> {
rvTest[0] = view;
view.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
view.requestLayout();
}));
recyclerView.perform(viewAction);
int startWidth = rvTest[0].getHeight();
//act
recyclerView.perform(
actionDelegate(((uiController, view) -> items.remove(9))),
notifyItemRemovedAction(9));
InstrumentalUtil.waitForIdle();
//assert
int endWidth = rvTest[0].getWidth();
System.out.println(String.format(Locale.getDefault(), "start height = %d, end height = %d", startWidth, endWidth));
assertTrue(endWidth < startWidth);
}
@Test
public void deleteItemInTheFirstLine_ItemHasMaximumWidth_SameStartPadding() throws Exception {
//arrange
{
//just adapt input items list to required start values
items.remove(1);
items.remove(9);
ChipsEntity longItem = items.remove(8);
items.add(1, longItem);
}
activity.runOnUiThread(() -> activity.initialize());
ViewInteraction recyclerView = onView(withId(R.id.rvTest)).check(matches(isDisplayed()));
//just adapt input items list to required start values
InstrumentalUtil.waitForIdle();
View second = layoutManager.getChildAt(1);
double expectedX = second.getX();
//act
recyclerView.perform(
actionDelegate(((uiController, view) -> items.remove(1))),
notifyItemRemovedAction(1));
InstrumentalUtil.waitForIdle();
second = layoutManager.getChildAt(5);
double resultX = second.getX();
//assert
assertNotEquals(0, expectedX, 0.01);
assertNotEquals(0, resultX, 0.01);
assertEquals(resultX, expectedX, 0.01);
}
}