1 package com.xtremelabs.robolectric.shadows; 2 3 import android.os.Looper; 4 import android.view.View; 5 import android.view.ViewGroup; 6 import android.widget.AdapterView; 7 import android.widget.TextView; 8 import com.xtremelabs.robolectric.Robolectric; 9 import com.xtremelabs.robolectric.util.Transcript; 10 11 import static com.xtremelabs.robolectric.Robolectric.*; 12 import static com.xtremelabs.robolectric.matchers.TextViewHasTextMatcher.hasText; 13 import static org.hamcrest.CoreMatchers.equalTo; 14 import static org.hamcrest.CoreMatchers.is; 15 import static org.hamcrest.CoreMatchers.not; 16 import static org.hamcrest.CoreMatchers.nullValue; 17 import static org.hamcrest.CoreMatchers.sameInstance; 18 import static org.hamcrest.core.CombinableMatcher.both; 19 import static org.junit.Assert.assertThat; 20 21 public class AdapterViewBehavior { 22 public static void shouldActAsAdapterView(AdapterView adapterView) throws Exception { 23 Robolectric.shadowOf(Looper.getMainLooper()).pause(); 24 25 testSetAdapter_ShouldCauseViewsToBeRenderedAsynchronously(adapterView); 26 testSetAdapter_ShouldSelectFirstItemAsynchronously(adapterView); 27 testSetAdapter_ShouldFireOnNothingSelectedWhenAdapterCountIsReducedToZero(adapterView); 28 29 shouldIgnoreSetSelectionCallsWithInvalidPosition(adapterView); 30 shouldOnlyUpdateOnceIfInvalidatedMultipleTimes(adapterView); 31 32 testSetEmptyView_ShouldHideAdapterViewIfAdapterIsNull(adapterView); 33 testSetEmptyView_ShouldHideAdapterViewIfAdapterViewIsEmpty(adapterView); 34 testSetEmptyView_ShouldHideEmptyViewIfAdapterViewIsNotEmpty(adapterView); 35 testSetEmptyView_ShouldHideEmptyViewWhenAdapterGetsNewItem(adapterView); 36 } 37 38 private static void shouldIgnoreSetSelectionCallsWithInvalidPosition(AdapterView adapterView) { 39 final Transcript transcript = new Transcript(); 40 41 adapterView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 42 @Override 43 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 44 transcript.add("onItemSelected fired"); 45 } 46 47 @Override 48 public void onNothingSelected(AdapterView<?> parent) { 49 } 50 }); 51 52 ShadowHandler.idleMainLooper(); 53 transcript.assertNoEventsSoFar(); 54 adapterView.setSelection(AdapterView.INVALID_POSITION); 55 ShadowHandler.idleMainLooper(); 56 transcript.assertNoEventsSoFar(); 57 } 58 59 private static void testSetAdapter_ShouldCauseViewsToBeRenderedAsynchronously(AdapterView adapterView) throws Exception { 60 adapterView.setAdapter(new CountingAdapter(2)); 61 62 assertThat(adapterView.getCount(), equalTo(2)); 63 assertThat(adapterView.getChildCount(), equalTo(0)); 64 65 ShadowHandler.idleMainLooper(); 66 assertThat(adapterView.getChildCount(), equalTo(2)); 67 assertThat((TextView) adapterView.getChildAt(0), hasText("Item 0")); 68 assertThat((TextView) adapterView.getChildAt(1), hasText("Item 1")); 69 } 70 71 private static void testSetAdapter_ShouldSelectFirstItemAsynchronously(final AdapterView adapterView) throws Exception { 72 final Transcript transcript = new Transcript(); 73 74 adapterView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 75 @Override 76 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 77 assertThat(parent, sameInstance(adapterView)); 78 assertThat(view, both(sameInstance(adapterView.getChildAt(position))).and(not(nullValue()))); 79 assertThat(id, equalTo(adapterView.getAdapter().getItemId(position))); 80 transcript.add("selected item " + position); 81 } 82 83 @Override 84 public void onNothingSelected(AdapterView<?> parent) { 85 } 86 }); 87 adapterView.setAdapter(new CountingAdapter(2)); 88 transcript.assertNoEventsSoFar(); 89 ShadowHandler.idleMainLooper(); 90 transcript.assertEventsSoFar("selected item 0"); 91 } 92 93 private static void testSetAdapter_ShouldFireOnNothingSelectedWhenAdapterCountIsReducedToZero(final AdapterView adapterView) throws Exception { 94 final Transcript transcript = new Transcript(); 95 96 adapterView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 97 @Override 98 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 99 } 100 101 @Override 102 public void onNothingSelected(AdapterView<?> parent) { 103 transcript.add("onNothingSelected fired"); 104 } 105 }); 106 CountingAdapter adapter = new CountingAdapter(2); 107 adapterView.setAdapter(adapter); 108 ShadowHandler.idleMainLooper(); 109 transcript.assertNoEventsSoFar(); 110 adapter.setCount(0); 111 ShadowHandler.idleMainLooper(); 112 transcript.assertEventsSoFar("onNothingSelected fired"); 113 } 114 115 private static void testSetEmptyView_ShouldHideAdapterViewIfAdapterIsNull(final AdapterView adapterView) throws Exception { 116 adapterView.setAdapter(null); 117 118 View emptyView = new View(adapterView.getContext()); 119 adapterView.setEmptyView(emptyView); 120 121 assertThat(adapterView.getVisibility(), is(View.GONE)); 122 assertThat(emptyView.getVisibility(), is(View.VISIBLE)); 123 } 124 125 private static void testSetEmptyView_ShouldHideAdapterViewIfAdapterViewIsEmpty(final AdapterView adapterView) throws Exception { 126 adapterView.setAdapter(new CountingAdapter(0)); 127 128 View emptyView = new View(adapterView.getContext()); 129 adapterView.setEmptyView(emptyView); 130 131 assertThat(adapterView.getVisibility(), is(View.GONE)); 132 assertThat(emptyView.getVisibility(), is(View.VISIBLE)); 133 } 134 135 private static void testSetEmptyView_ShouldHideEmptyViewIfAdapterViewIsNotEmpty(final AdapterView adapterView) throws Exception { 136 adapterView.setAdapter(new CountingAdapter(1)); 137 138 View emptyView = new View(adapterView.getContext()); 139 adapterView.setEmptyView(emptyView); 140 141 assertThat(adapterView.getVisibility(), is(View.VISIBLE)); 142 assertThat(emptyView.getVisibility(), is(View.GONE)); 143 } 144 145 private static void testSetEmptyView_ShouldHideEmptyViewWhenAdapterGetsNewItem(final AdapterView adapterView) throws Exception { 146 CountingAdapter adapter = new CountingAdapter(0); 147 adapterView.setAdapter(adapter); 148 149 View emptyView = new View(adapterView.getContext()); 150 adapterView.setEmptyView(emptyView); 151 152 assertThat(adapterView.getVisibility(), is(View.GONE)); 153 assertThat(emptyView.getVisibility(), is(View.VISIBLE)); 154 155 adapter.setCount(1); 156 157 ShadowHandler.idleMainLooper(); 158 159 assertThat(adapterView.getVisibility(), is(View.VISIBLE)); 160 assertThat(emptyView.getVisibility(), is(View.GONE)); 161 } 162 163 private static void testSetEmptyView_ShouldHideAdapterViewWhenAdapterBecomesEmpty(final AdapterView adapterView) throws Exception { 164 CountingAdapter adapter = new CountingAdapter(1); 165 adapterView.setAdapter(adapter); 166 167 View emptyView = new View(adapterView.getContext()); 168 adapterView.setEmptyView(emptyView); 169 170 assertThat(adapterView.getVisibility(), is(View.GONE)); 171 assertThat(emptyView.getVisibility(), is(View.VISIBLE)); 172 173 adapter.setCount(0); 174 175 ShadowHandler.idleMainLooper(); 176 177 assertThat(adapterView.getVisibility(), is(View.VISIBLE)); 178 assertThat(emptyView.getVisibility(), is(View.GONE)); 179 } 180 181 private static void shouldOnlyUpdateOnceIfInvalidatedMultipleTimes(final AdapterView adapterView) { 182 final Transcript transcript = new Transcript(); 183 CountingAdapter adapter = new CountingAdapter(2) { 184 @Override 185 public View getView(int position, View convertView, ViewGroup parent) { 186 transcript.add("getView for " + position); 187 return super.getView(position, convertView, parent); 188 } 189 }; 190 adapterView.setAdapter(adapter); 191 192 transcript.assertNoEventsSoFar(); 193 194 adapter.notifyDataSetChanged(); 195 adapter.notifyDataSetChanged(); 196 197 ShadowHandler.idleMainLooper(); 198 199 transcript.assertEventsSoFar("getView for 0", "getView for 1"); 200 } 201 } 202