1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.support.v7.widget; 18 19 import org.junit.After; 20 import org.junit.Before; 21 import org.junit.Test; 22 import org.junit.runner.RunWith; 23 24 import android.content.Context; 25 import android.support.annotation.Nullable; 26 import android.support.test.InstrumentationRegistry; 27 import android.support.test.runner.AndroidJUnit4; 28 import android.test.AndroidTestCase; 29 import android.test.suitebuilder.annotation.MediumTest; 30 import android.view.Display; 31 import android.view.View; 32 import android.view.ViewGroup; 33 34 import static org.mockito.Mockito.any; 35 import static org.mockito.Mockito.anyInt; 36 import static org.mockito.Mockito.doReturn; 37 import static org.mockito.Mockito.eq; 38 import static org.mockito.Mockito.mock; 39 import static org.mockito.Mockito.spy; 40 import static org.mockito.Mockito.times; 41 import static org.mockito.Mockito.verify; 42 import static org.mockito.Mockito.when; 43 44 @MediumTest 45 @RunWith(AndroidJUnit4.class) 46 public class WrapContentBasicTest extends AndroidTestCase { 47 48 private WrapContentLayoutManager mLayoutManager; 49 private RecyclerView mRecyclerView; 50 private WrapAdapter mAdapter; 51 private static int WRAP = View.MeasureSpec.makeMeasureSpec(10, View.MeasureSpec.AT_MOST); 52 private static int EXACT = View.MeasureSpec.makeMeasureSpec(10, View.MeasureSpec.EXACTLY); 53 private static int UNSPECIFIED = View.MeasureSpec 54 .makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); 55 56 @Before 57 @Override setUp()58 public void setUp() throws Exception { 59 super.setUp(); 60 setContext(InstrumentationRegistry.getContext()); 61 RecyclerView rv = new RecyclerView(getContext()); 62 mRecyclerView = spy(rv); 63 mLayoutManager = spy(new WrapContentLayoutManager()); 64 // working around a mockito issue 65 rv.mLayout = mLayoutManager; 66 mAdapter = spy(new WrapAdapter()); 67 mRecyclerView.setLayoutManager(mLayoutManager); 68 mRecyclerView.setAdapter(mAdapter); 69 } 70 71 @After 72 @Override tearDown()73 public void tearDown() throws Exception { 74 super.tearDown(); 75 } 76 77 @Test testLayoutInOnMeasureWithoutPredictive()78 public void testLayoutInOnMeasureWithoutPredictive() { 79 mLayoutManager.setAutoMeasureEnabled(true); 80 when(mLayoutManager.supportsPredictiveItemAnimations()).thenReturn(false); 81 mRecyclerView.onMeasure(WRAP, WRAP); 82 mRecyclerView.onMeasure(WRAP, WRAP); 83 mRecyclerView.onLayout(true, 0, 10, 10, 10); 84 verify(mLayoutManager, times(3)) 85 .onLayoutChildren(mRecyclerView.mRecycler, mRecyclerView.mState); 86 } 87 88 @Test dataChangeAfterMeasure()89 public void dataChangeAfterMeasure() { 90 mLayoutManager.setAutoMeasureEnabled(true); 91 mRecyclerView.onMeasure(WRAP, WRAP); 92 mRecyclerView.onMeasure(WRAP, WRAP); 93 mAdapter.notifyItemChanged(1); 94 mRecyclerView.onLayout(true, 0, 10, 10, 10); 95 verify(mLayoutManager, times(3)) 96 .onLayoutChildren(mRecyclerView.mRecycler, mRecyclerView.mState); 97 } 98 99 @Test setDimensionsFromChildren()100 public void setDimensionsFromChildren() { 101 mLayoutManager.setAutoMeasureEnabled(true); 102 View[] children = createMockChildren(3); 103 mLayoutManager.setMeasuredDimensionFromChildren(WRAP, WRAP); 104 verify(mLayoutManager).setMeasuredDimension(children[0].getWidth(), 105 children[0].getHeight()); 106 } 107 108 @Test setDimensionsFromChildrenAnsSpec1()109 public void setDimensionsFromChildrenAnsSpec1() { 110 mLayoutManager.setAutoMeasureEnabled(true); 111 View[] children = createMockChildren(3); 112 int hSpec = View.MeasureSpec.makeMeasureSpec(111, View.MeasureSpec.EXACTLY); 113 mLayoutManager.setMeasuredDimensionFromChildren(WRAP, hSpec); 114 verify(mLayoutManager).setMeasuredDimension(children[0].getWidth(), 111); 115 } 116 117 @Test setDimensionsFromChildrenAnsSpec2()118 public void setDimensionsFromChildrenAnsSpec2() { 119 mLayoutManager.setAutoMeasureEnabled(true); 120 View[] children = createMockChildren(3); 121 int wSpec = View.MeasureSpec.makeMeasureSpec(111, View.MeasureSpec.EXACTLY); 122 mLayoutManager.setMeasuredDimensionFromChildren(wSpec, WRAP); 123 verify(mLayoutManager).setMeasuredDimension(111, children[0].getHeight()); 124 } 125 126 @Test setDimensionsFromChildrenAnsSpec3()127 public void setDimensionsFromChildrenAnsSpec3() { 128 mLayoutManager.setAutoMeasureEnabled(true); 129 View[] children = createMockChildren(3); 130 children[0].layout(0, 0, 100, 100); 131 children[1].layout(-5, 0, 100, 100); 132 children[2].layout(-5, -10, 100, 100); 133 mLayoutManager.setMeasuredDimensionFromChildren(UNSPECIFIED, UNSPECIFIED); 134 verify(mLayoutManager).setMeasuredDimension(105, 110); 135 } 136 137 @Test setDimensionsFromChildrenAnsSpec4()138 public void setDimensionsFromChildrenAnsSpec4() { 139 mLayoutManager.setAutoMeasureEnabled(true); 140 View[] children = createMockChildren(3); 141 children[0].layout(0, 0, 100, 100); 142 children[1].layout(-5, 0, 100, 100); 143 children[2].layout(-5, -10, 100, 100); 144 int atMost = View.MeasureSpec.makeMeasureSpec(95, View.MeasureSpec.AT_MOST); 145 mLayoutManager.setMeasuredDimensionFromChildren(atMost, atMost); 146 verify(mLayoutManager).setMeasuredDimension(95, 95); 147 } 148 149 @Test setDimensionsFromChildrenAnsSpec5()150 public void setDimensionsFromChildrenAnsSpec5() { 151 mLayoutManager.setAutoMeasureEnabled(true); 152 View[] children = createMockChildren(3); 153 children[0].layout(0, 0, 100, 100); 154 children[1].layout(-5, 0, 100, 100); 155 children[2].layout(-5, -10, 100, 100); 156 when(mRecyclerView.getMinimumWidth()).thenReturn(250); 157 mLayoutManager.setMeasuredDimensionFromChildren(UNSPECIFIED, UNSPECIFIED); 158 verify(mLayoutManager).setMeasuredDimension(250, 110); 159 160 when(mRecyclerView.getMinimumWidth()).thenReturn(5); 161 mLayoutManager.setMeasuredDimensionFromChildren(UNSPECIFIED, UNSPECIFIED); 162 verify(mLayoutManager).setMeasuredDimension(105, 110); 163 } 164 165 @Test setDimensionsFromChildrenAnsSpec6()166 public void setDimensionsFromChildrenAnsSpec6() { 167 mLayoutManager.setAutoMeasureEnabled(true); 168 View[] children = createMockChildren(3); 169 children[0].layout(0, 0, 100, 100); 170 children[1].layout(-5, 0, 100, 100); 171 children[2].layout(-5, -10, 100, 100); 172 when(mRecyclerView.getMinimumHeight()).thenReturn(250); 173 mLayoutManager.setMeasuredDimensionFromChildren(UNSPECIFIED, UNSPECIFIED); 174 verify(mLayoutManager).setMeasuredDimension(105, 250); 175 176 when(mRecyclerView.getMinimumHeight()).thenReturn(50); 177 mLayoutManager.setMeasuredDimensionFromChildren(UNSPECIFIED, UNSPECIFIED); 178 verify(mLayoutManager).setMeasuredDimension(105, 110); 179 } 180 createMockChildren(int count)181 private View[] createMockChildren(int count) { 182 View[] views = new View[count]; 183 for (int i = 0; i < count; i++) { 184 View v = new View(getContext()); 185 v.setLayoutParams(new RecyclerView.LayoutParams(1, 1)); 186 views[i] = v; 187 when(mLayoutManager.getChildAt(i)).thenReturn(v); 188 } 189 when(mLayoutManager.getChildCount()).thenReturn(3); 190 return views; 191 } 192 193 public class WrapContentLayoutManager extends RecyclerView.LayoutManager { 194 195 @Override onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state)196 public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { 197 198 } 199 200 @Override generateDefaultLayoutParams()201 public RecyclerView.LayoutParams generateDefaultLayoutParams() { 202 return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 203 ViewGroup.LayoutParams.WRAP_CONTENT); 204 } 205 } 206 207 public class WrapAdapter extends RecyclerView.Adapter { 208 209 @Override onCreateViewHolder(ViewGroup parent, int viewType)210 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 211 return null; 212 } 213 214 @Override onBindViewHolder(RecyclerView.ViewHolder holder, int position)215 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 216 217 } 218 219 @Override getItemCount()220 public int getItemCount() { 221 return 10; 222 } 223 } 224 } 225