1 /* 2 * Copyright 2018 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 18 package androidx.fragment.app; 19 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertNull; 22 import static org.junit.Assert.assertSame; 23 import static org.junit.Assert.assertTrue; 24 25 import android.support.test.filters.MediumTest; 26 import android.support.test.rule.ActivityTestRule; 27 import android.support.test.runner.AndroidJUnit4; 28 29 import androidx.fragment.app.test.EmptyFragmentTestActivity; 30 31 import org.junit.Rule; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 35 @RunWith(AndroidJUnit4.class) 36 @MediumTest 37 public class PrimaryNavFragmentTest { 38 @Rule 39 public ActivityTestRule<EmptyFragmentTestActivity> mActivityRule = 40 new ActivityTestRule<EmptyFragmentTestActivity>(EmptyFragmentTestActivity.class); 41 42 @Test 43 public void delegateBackToPrimaryNav() throws Throwable { 44 final FragmentManager fm = mActivityRule.getActivity().getSupportFragmentManager(); 45 final StrictFragment strictFragment = new StrictFragment(); 46 47 fm.beginTransaction().add(strictFragment, null).setPrimaryNavigationFragment(strictFragment) 48 .commit(); 49 executePendingTransactions(fm); 50 51 assertSame("new fragment is not primary nav fragment", strictFragment, 52 fm.getPrimaryNavigationFragment()); 53 54 final StrictFragment child = new StrictFragment(); 55 FragmentManager cfm = strictFragment.getChildFragmentManager(); 56 cfm.beginTransaction().add(child, null).addToBackStack(null).commit(); 57 executePendingTransactions(cfm); 58 59 assertEquals("child transaction not on back stack", 1, cfm.getBackStackEntryCount()); 60 61 // Should execute the pop for the child fragmentmanager 62 assertTrue("popBackStackImmediate returned no action performed", 63 popBackStackImmediate(fm)); 64 65 assertEquals("child transaction still on back stack", 0, cfm.getBackStackEntryCount()); 66 } 67 68 @Test 69 public void popPrimaryNav() throws Throwable { 70 final FragmentManager fm = mActivityRule.getActivity().getSupportFragmentManager(); 71 final StrictFragment strictFragment1 = new StrictFragment(); 72 73 fm.beginTransaction().add(strictFragment1, null) 74 .setPrimaryNavigationFragment(strictFragment1) 75 .commit(); 76 executePendingTransactions(fm); 77 78 assertSame("new fragment is not primary nav fragment", strictFragment1, 79 fm.getPrimaryNavigationFragment()); 80 81 fm.beginTransaction().remove(strictFragment1).addToBackStack(null).commit(); 82 executePendingTransactions(fm); 83 84 assertNull("primary nav fragment is not null after remove", 85 fm.getPrimaryNavigationFragment()); 86 87 popBackStackImmediate(fm); 88 89 assertSame("primary nav fragment was not restored on pop", strictFragment1, 90 fm.getPrimaryNavigationFragment()); 91 92 final StrictFragment strictFragment2 = new StrictFragment(); 93 fm.beginTransaction().remove(strictFragment1).add(strictFragment2, null) 94 .setPrimaryNavigationFragment(strictFragment2).addToBackStack(null).commit(); 95 executePendingTransactions(fm); 96 97 assertSame("primary nav fragment not updated to new fragment", strictFragment2, 98 fm.getPrimaryNavigationFragment()); 99 100 popBackStackImmediate(fm); 101 102 assertSame("primary nav fragment not restored on pop", strictFragment1, 103 fm.getPrimaryNavigationFragment()); 104 105 fm.beginTransaction().setPrimaryNavigationFragment(strictFragment1) 106 .addToBackStack(null).commit(); 107 executePendingTransactions(fm); 108 109 assertSame("primary nav fragment not retained when set again in new transaction", 110 strictFragment1, fm.getPrimaryNavigationFragment()); 111 popBackStackImmediate(fm); 112 113 assertSame("same primary nav fragment not retained when set primary nav transaction popped", 114 strictFragment1, fm.getPrimaryNavigationFragment()); 115 } 116 117 @Test 118 public void replacePrimaryNav() throws Throwable { 119 final FragmentManager fm = mActivityRule.getActivity().getSupportFragmentManager(); 120 final StrictFragment strictFragment1 = new StrictFragment(); 121 122 fm.beginTransaction().add(android.R.id.content, strictFragment1) 123 .setPrimaryNavigationFragment(strictFragment1).commit(); 124 executePendingTransactions(fm); 125 126 assertSame("new fragment is not primary nav fragment", strictFragment1, 127 fm.getPrimaryNavigationFragment()); 128 129 final StrictFragment strictFragment2 = new StrictFragment(); 130 fm.beginTransaction().replace(android.R.id.content, strictFragment2) 131 .addToBackStack(null).commit(); 132 133 executePendingTransactions(fm); 134 135 assertNull("primary nav fragment not null after replace", 136 fm.getPrimaryNavigationFragment()); 137 138 popBackStackImmediate(fm); 139 140 assertSame("primary nav fragment not restored after popping replace", strictFragment1, 141 fm.getPrimaryNavigationFragment()); 142 143 fm.beginTransaction().setPrimaryNavigationFragment(null).commit(); 144 executePendingTransactions(fm); 145 146 assertNull("primary nav fragment not null after explicit set to null", 147 fm.getPrimaryNavigationFragment()); 148 149 fm.beginTransaction().replace(android.R.id.content, strictFragment2) 150 .setPrimaryNavigationFragment(strictFragment2).addToBackStack(null).commit(); 151 executePendingTransactions(fm); 152 153 assertSame("primary nav fragment not set correctly after replace", strictFragment2, 154 fm.getPrimaryNavigationFragment()); 155 156 popBackStackImmediate(fm); 157 158 assertNull("primary nav fragment not null after popping replace", 159 fm.getPrimaryNavigationFragment()); 160 } 161 162 private void executePendingTransactions(final FragmentManager fm) throws Throwable { 163 mActivityRule.runOnUiThread(new Runnable() { 164 @Override 165 public void run() { 166 fm.executePendingTransactions(); 167 } 168 }); 169 } 170 171 private boolean popBackStackImmediate(final FragmentManager fm) throws Throwable { 172 final boolean[] result = new boolean[1]; 173 mActivityRule.runOnUiThread(new Runnable() { 174 @Override 175 public void run() { 176 result[0] = fm.popBackStackImmediate(); 177 } 178 }); 179 return result[0]; 180 } 181 } 182