1 package com.xtremelabs.robolectric.shadows; 2 3 import android.os.Bundle; 4 import android.os.Handler; 5 import android.os.Looper; 6 import android.support.v4.app.Fragment; 7 import android.support.v4.app.FragmentActivity; 8 import android.support.v4.app.FragmentTransaction; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.view.ViewGroup; 12 import android.widget.Button; 13 import android.widget.FrameLayout; 14 import com.xtremelabs.robolectric.Robolectric; 15 import com.xtremelabs.robolectric.WithTestDefaultsRunner; 16 import com.xtremelabs.robolectric.tester.android.util.TestFragmentManager; 17 import com.xtremelabs.robolectric.util.Scheduler; 18 import com.xtremelabs.robolectric.util.TestRunnable; 19 import org.junit.Before; 20 import org.junit.Test; 21 import org.junit.runner.RunWith; 22 23 import static com.xtremelabs.robolectric.Robolectric.shadowOf; 24 import static org.hamcrest.CoreMatchers.equalTo; 25 import static org.hamcrest.CoreMatchers.sameInstance; 26 import static org.hamcrest.MatcherAssert.assertThat; 27 import static org.junit.Assert.*; 28 29 @RunWith(WithTestDefaultsRunner.class) 30 public class FragmentManagerTest { 31 32 public static final int CONTAINER_VIEW_ID = 888; 33 private TestFragmentManager manager; 34 private TestFragment fragment; 35 private TestFragmentActivity activity; 36 private ViewGroup containerView; 37 38 @Before 39 public void setUp() throws Exception { 40 activity = new TestFragmentActivity(); 41 activity.onCreate(null); 42 manager = (TestFragmentManager) activity.getSupportFragmentManager(); 43 fragment = new TestFragment(); 44 containerView = (ViewGroup) activity.findViewById(CONTAINER_VIEW_ID); 45 } 46 47 @Test 48 public void shouldFindFragmentById() throws Exception { 49 manager.addFragment(CONTAINER_VIEW_ID, "tag1", fragment, false); 50 51 assertThat(manager.findFragmentById(CONTAINER_VIEW_ID), sameInstance((Fragment) fragment)); 52 } 53 54 @Test 55 public void shouldFindFragmentByTag() throws Exception { 56 manager.addFragment(CONTAINER_VIEW_ID, "tag1", fragment, false); 57 58 assertThat(manager.findFragmentByTag("tag1"), sameInstance((Fragment) fragment)); 59 } 60 61 @Test 62 public void addFragment_shouldCallLifecycleMethods() throws Exception { 63 manager.addFragment(View.NO_ID, null, fragment, false); 64 65 fragment.transcript.assertEventsSoFar( 66 "onAttach", 67 "onCreate" 68 ); 69 70 assertSame(activity, fragment.onAttachActivity); 71 assertSame(activity, fragment.getActivity()); 72 } 73 74 @Test 75 public void startFragment_shouldCallLifecycleMethods() throws Exception { 76 manager.addFragment(View.NO_ID, null, fragment, false); 77 fragment.transcript.clear(); 78 manager.startFragment(fragment); 79 80 fragment.transcript.assertEventsSoFar( 81 "onCreateView", 82 "onViewCreated", 83 "onActivityCreated", 84 "onStart" 85 ); 86 87 assertEquals(fragment.onCreateViewInflater, activity.getLayoutInflater()); 88 assertNotNull(fragment.getView()); 89 } 90 91 @Test 92 public void addFragment_shouldSetTheFragmentsView() throws Exception { 93 manager.addFragment(View.NO_ID, null, fragment, false); 94 95 assertThat(fragment.getView(), sameInstance(fragment.onCreateViewReturnValue)); 96 } 97 98 @Test 99 public void addFragment_shouldSetTheFragmentsTag() throws Exception { 100 manager.addFragment(View.NO_ID, "expected tag", fragment, false); 101 102 assertThat(fragment.getTag(), equalTo("expected tag")); 103 } 104 105 @Test 106 public void startFragment_shouldInsertTheFragmentViewIntoTheContainerView() throws Exception { 107 manager.addFragment(CONTAINER_VIEW_ID, null, fragment, false); 108 manager.startFragment(fragment); 109 110 View fragmentViewParent = (View) activity.findViewById(TestFragment.FRAGMENT_VIEW_ID).getParent(); 111 assertThat(activity.findViewById(TestFragment.FRAGMENT_VIEW_ID), sameInstance(fragment.onCreateViewReturnValue)); 112 assertThat(fragmentViewParent, sameInstance((View) containerView)); 113 } 114 115 @Test 116 public void addFragmentWithReplace_shouldEmptyTheContainer() throws Exception { 117 containerView.addView(new Button(activity)); 118 assertEquals(1, containerView.getChildCount()); 119 120 manager.addFragment(CONTAINER_VIEW_ID, null, fragment, true); 121 122 assertEquals(1, containerView.getChildCount()); 123 } 124 125 @Test 126 public void addFragmentWithReplace_withNoContainer_shouldNotThrow() throws Exception { 127 manager.addFragment(0, null, fragment, true); 128 // pass 129 } 130 131 @Test 132 public void addFragment_shouldSetFragmentsActivity() throws Exception { 133 manager.addFragment(0, null, fragment, false); 134 135 assertSame(activity, fragment.getActivity()); 136 } 137 138 @Test 139 public void addFragment_shouldPassTheSavedInstanceStateToOnCreate() throws Exception { 140 Bundle bundle = new Bundle(); 141 shadowOf(fragment).setSavedInstanceState(bundle); 142 manager.addFragment(0, null, fragment, false); 143 assertSame(bundle, fragment.onCreateSavedInstanceState); 144 } 145 146 @Test 147 public void getFragment_whenBundleSavedByShadowFragmentActivity_shouldGetFragmentByTagFromBundle() throws Exception { 148 manager.addFragment(CONTAINER_VIEW_ID, "fragment tag", fragment, true); 149 150 Bundle outState = new Bundle(); 151 shadowOf(activity).onSaveInstanceState(outState); 152 153 Fragment retrievedFragment = manager.getFragment(outState, "fragment tag"); 154 assertEquals(TestFragment.class, retrievedFragment.getClass()); 155 } 156 157 @Test 158 public void startFragment_shouldPassSavedInstanceStateToOnCreateMethodOfFragment() throws Exception { 159 shadowOf(fragment).setSavedInstanceState(new Bundle()); 160 manager.addFragment(CONTAINER_VIEW_ID, null, fragment, true); 161 manager.startFragment(fragment); 162 163 assertTrue(fragment.onActivityCreated_savedInstanceState != null); 164 } 165 166 @Test 167 public void getCommittedTransactions_shouldReturnListOfOnlyCommittedTransactions() throws Exception { 168 assertTrue(manager.getCommittedTransactions().isEmpty()); 169 170 FragmentTransaction transaction = manager.beginTransaction(); 171 assertTrue(manager.getCommittedTransactions().isEmpty()); 172 173 transaction.add(new Fragment(), "tag"); 174 transaction.commit(); 175 assertEquals(1, manager.getCommittedTransactions().size()); 176 assertSame(transaction, manager.getCommittedTransactions().get(0)); 177 178 FragmentTransaction anotherTransaction = manager.beginTransaction(); 179 anotherTransaction.add(new Fragment(), "tag"); 180 anotherTransaction.commit(); 181 assertEquals(2, manager.getCommittedTransactions().size()); 182 assertSame(anotherTransaction, manager.getCommittedTransactions().get(1)); 183 } 184 185 @Test 186 public void shouldBeAbleToCommitTransactions_whenTheFragmentHasNoView() throws Exception { 187 TestFragment fragment = new TestFragment() { 188 @Override 189 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 190 return null; 191 } 192 }; 193 194 activity.getSupportFragmentManager().beginTransaction().add(CONTAINER_VIEW_ID, fragment).commit(); 195 196 assertSame(fragment, activity.getSupportFragmentManager().findFragmentById(CONTAINER_VIEW_ID)); 197 } 198 199 @Test 200 public void executePendingTransactions_shouldRunPendingCommitsAsIfTheMainLooperWereNotPaused() throws Exception { 201 Robolectric.pauseMainLooper(); 202 Scheduler scheduler = shadowOf(Looper.getMainLooper()).getScheduler(); 203 Fragment fragment2 = new Fragment(); 204 205 TestRunnable otherEnqueuedTask = new TestRunnable(); 206 new Handler(Looper.getMainLooper()).post(otherEnqueuedTask); 207 208 manager.beginTransaction().add(fragment, "fragment1").commit(); 209 manager.beginTransaction().add(fragment2, "fragment2").commit(); 210 211 assertEquals(3, scheduler.enqueuedTaskCount()); 212 assertNull(manager.findFragmentByTag("fragment1")); 213 assertNull(manager.findFragmentByTag("fragment2")); 214 215 boolean ranSomeTransactions = manager.executePendingTransactions(); 216 assertTrue(ranSomeTransactions); 217 assertSame(fragment, manager.findFragmentByTag("fragment1")); 218 assertSame(fragment2, manager.findFragmentByTag("fragment2")); 219 assertEquals(1, scheduler.enqueuedTaskCount()); 220 221 assertFalse(otherEnqueuedTask.wasRun); 222 Robolectric.unPauseMainLooper(); 223 assertTrue(otherEnqueuedTask.wasRun); 224 225 ranSomeTransactions = manager.executePendingTransactions(); 226 assertFalse(ranSomeTransactions); 227 } 228 229 @Test 230 public void executePendingTransactions_shouldAvoidRunningTransactionsThatWereAlreadyRun() throws Exception { 231 manager.beginTransaction().add(fragment, "tag").commit(); 232 assertEquals(1, manager.getCommittedTransactions().size()); 233 234 boolean ranSomeTransactions = manager.executePendingTransactions(); 235 assertFalse(ranSomeTransactions); 236 assertEquals(1, manager.getCommittedTransactions().size()); 237 } 238 239 private static class TestFragmentActivity extends FragmentActivity { 240 @Override 241 public void onCreate(Bundle savedInstanceState) { 242 super.onCreate(savedInstanceState); 243 View view = new FrameLayout(this); 244 view.setId(CONTAINER_VIEW_ID); 245 setContentView(view); 246 } 247 } 248 249 } 250