blob: 7fd80a3fb5dcf4159279a8f88bd03fee0562be17 [file] [log] [blame]
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.recyclerview.widget;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@MediumTest
@RunWith(AndroidJUnit4.class)
public class WrapContentBasicTest {
private Context mContext;
private WrapContentLayoutManager mLayoutManager;
private RecyclerView mRecyclerView;
private WrapAdapter mAdapter;
private static int WRAP = View.MeasureSpec.makeMeasureSpec(10, View.MeasureSpec.AT_MOST);
private static int EXACT = View.MeasureSpec.makeMeasureSpec(10, View.MeasureSpec.EXACTLY);
private static int UNSPECIFIED = View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
@Before
public void setup() throws Exception {
mContext = InstrumentationRegistry.getContext();
mRecyclerView = new RecyclerView(mContext);
mLayoutManager = spy(new WrapContentLayoutManager());
// working around a mockito issue
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = spy(new WrapAdapter());
mRecyclerView.setAdapter(mAdapter);
}
@Test
public void testLayoutInOnMeasureWithoutPredictive() {
when(mLayoutManager.supportsPredictiveItemAnimations()).thenReturn(false);
mRecyclerView.onMeasure(WRAP, WRAP);
mRecyclerView.onMeasure(WRAP, WRAP);
mRecyclerView.onLayout(true, 0, 10, 10, 10);
verify(mLayoutManager, times(3))
.onLayoutChildren(mRecyclerView.mRecycler, mRecyclerView.mState);
}
@Test
public void dataChangeAfterMeasure() {
mRecyclerView.onMeasure(WRAP, WRAP);
mRecyclerView.onMeasure(WRAP, WRAP);
mAdapter.notifyItemChanged(1);
mRecyclerView.onLayout(true, 0, 10, 10, 10);
verify(mLayoutManager, times(3))
.onLayoutChildren(mRecyclerView.mRecycler, mRecyclerView.mState);
}
@Test
public void setDimensionsFromChildren() {
View[] children = createMockChildren(3);
mLayoutManager.setMeasuredDimensionFromChildren(WRAP, WRAP);
verify(mLayoutManager).setMeasuredDimension(children[0].getWidth(),
children[0].getHeight());
}
@Test
public void setDimensionsFromChildrenAnsSpec1() {
View[] children = createMockChildren(3);
int hSpec = View.MeasureSpec.makeMeasureSpec(111, View.MeasureSpec.EXACTLY);
mLayoutManager.setMeasuredDimensionFromChildren(WRAP, hSpec);
verify(mLayoutManager).setMeasuredDimension(children[0].getWidth(), 111);
}
@Test
public void setDimensionsFromChildrenAnsSpec2() {
View[] children = createMockChildren(3);
int wSpec = View.MeasureSpec.makeMeasureSpec(111, View.MeasureSpec.EXACTLY);
mLayoutManager.setMeasuredDimensionFromChildren(wSpec, WRAP);
verify(mLayoutManager).setMeasuredDimension(111, children[0].getHeight());
}
@Test
public void setDimensionsFromChildrenAnsSpec3() {
View[] children = createMockChildren(3);
children[0].layout(0, 0, 100, 100);
children[1].layout(-5, 0, 100, 100);
children[2].layout(-5, -10, 100, 100);
mLayoutManager.setMeasuredDimensionFromChildren(UNSPECIFIED, UNSPECIFIED);
verify(mLayoutManager).setMeasuredDimension(105, 110);
}
@Test
public void setDimensionsFromChildrenAnsSpec4() {
View[] children = createMockChildren(3);
children[0].layout(0, 0, 100, 100);
children[1].layout(-5, 0, 100, 100);
children[2].layout(-5, -10, 100, 100);
int atMost = View.MeasureSpec.makeMeasureSpec(95, View.MeasureSpec.AT_MOST);
mLayoutManager.setMeasuredDimensionFromChildren(atMost, atMost);
verify(mLayoutManager).setMeasuredDimension(95, 95);
}
@Test
public void setDimensionsFromChildrenAnsSpec5() {
View[] children = createMockChildren(3);
children[0].layout(0, 0, 100, 100);
children[1].layout(-5, 0, 100, 100);
children[2].layout(-5, -10, 100, 100);
mRecyclerView.setMinimumWidth(250);
mLayoutManager.setMeasuredDimensionFromChildren(UNSPECIFIED, UNSPECIFIED);
verify(mLayoutManager).setMeasuredDimension(250, 110);
mRecyclerView.setMinimumWidth(5);
mLayoutManager.setMeasuredDimensionFromChildren(UNSPECIFIED, UNSPECIFIED);
verify(mLayoutManager).setMeasuredDimension(105, 110);
}
@Test
public void setDimensionsFromChildrenAnsSpec6() {
View[] children = createMockChildren(3);
children[0].layout(0, 0, 100, 100);
children[1].layout(-5, 0, 100, 100);
children[2].layout(-5, -10, 100, 100);
mRecyclerView.setMinimumHeight(250);
mLayoutManager.setMeasuredDimensionFromChildren(UNSPECIFIED, UNSPECIFIED);
verify(mLayoutManager).setMeasuredDimension(105, 250);
mRecyclerView.setMinimumHeight(50);
mLayoutManager.setMeasuredDimensionFromChildren(UNSPECIFIED, UNSPECIFIED);
verify(mLayoutManager).setMeasuredDimension(105, 110);
}
private View[] createMockChildren(int count) {
View[] views = new View[count];
for (int i = 0; i < count; i++) {
View v = new View(mContext);
v.setLayoutParams(new RecyclerView.LayoutParams(1, 1));
views[i] = v;
when(mLayoutManager.getChildAt(i)).thenReturn(v);
}
when(mLayoutManager.getChildCount()).thenReturn(3);
return views;
}
public class WrapContentLayoutManager extends RecyclerView.LayoutManager {
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
}
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
@Override
public boolean isAutoMeasureEnabled() {
return true;
}
// START MOCKITO OVERRIDES
// We override package protected methods to make them public. This is necessary to run
// mockito on Kitkat
@Override
public void setRecyclerView(RecyclerView recyclerView) {
super.setRecyclerView(recyclerView);
}
@Override
public void dispatchAttachedToWindow(RecyclerView view) {
super.dispatchAttachedToWindow(view);
}
@Override
public void dispatchDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) {
super.dispatchDetachedFromWindow(view, recycler);
}
@Override
public void setExactMeasureSpecsFrom(RecyclerView recyclerView) {
super.setExactMeasureSpecsFrom(recyclerView);
}
@Override
public void setMeasureSpecs(int wSpec, int hSpec) {
super.setMeasureSpecs(wSpec, hSpec);
}
@Override
public void setMeasuredDimensionFromChildren(int widthSpec, int heightSpec) {
super.setMeasuredDimensionFromChildren(widthSpec, heightSpec);
}
@Override
public boolean shouldReMeasureChild(View child, int widthSpec, int heightSpec,
RecyclerView.LayoutParams lp) {
return super.shouldReMeasureChild(child, widthSpec, heightSpec, lp);
}
@Override
public boolean shouldMeasureChild(View child, int widthSpec, int heightSpec,
RecyclerView.LayoutParams lp) {
return super.shouldMeasureChild(child, widthSpec, heightSpec, lp);
}
@Override
public void removeAndRecycleScrapInt(RecyclerView.Recycler recycler) {
super.removeAndRecycleScrapInt(recycler);
}
@Override
public void stopSmoothScroller() {
super.stopSmoothScroller();
}
@Override
public boolean shouldMeasureTwice() {
return super.shouldMeasureTwice();
}
// END MOCKITO OVERRIDES
}
public class WrapAdapter extends RecyclerView.Adapter {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 10;
}
}
}