| /* |
| * Copyright (C) 2016 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 android.fragment.cts; |
| |
| import static junit.framework.Assert.*; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import android.app.Fragment; |
| import android.app.FragmentManager; |
| import android.os.Bundle; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| |
| import androidx.test.filters.MediumTest; |
| import androidx.test.rule.ActivityTestRule; |
| import androidx.test.runner.AndroidJUnit4; |
| |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| @MediumTest |
| @RunWith(AndroidJUnit4.class) |
| public class FragmentViewTests { |
| @Rule |
| public ActivityTestRule<FragmentTestActivity> mActivityRule = |
| new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class); |
| |
| // Test that adding a fragment adds the Views in the proper order. Popping the back stack |
| // should remove the correct Views. |
| @Test |
| public void addFragments() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| |
| // One fragment with a view |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment1).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment1); |
| |
| // Add another on top |
| final StrictViewFragment fragment2 = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment2).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment1, fragment2); |
| |
| // Now add two in one transaction: |
| final StrictViewFragment fragment3 = new StrictViewFragment(); |
| final StrictViewFragment fragment4 = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment3) |
| .add(R.id.fragmentContainer, fragment4) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment1, fragment2, fragment3, fragment4); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment1, fragment2); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| assertEquals(1, container.getChildCount()); |
| FragmentTestUtil.assertChildren(container, fragment1); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container); |
| } |
| |
| // Add fragments to multiple containers in the same transaction. Make sure that |
| // they pop correctly, too. |
| @Test |
| public void addTwoContainers() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.double_container); |
| ViewGroup container1 = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer1); |
| ViewGroup container2 = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer2); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer1, fragment1).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container1, fragment1); |
| |
| final StrictViewFragment fragment2 = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer2, fragment2).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container2, fragment2); |
| |
| final StrictViewFragment fragment3 = new StrictViewFragment(); |
| final StrictViewFragment fragment4 = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer1, fragment3) |
| .add(R.id.fragmentContainer2, fragment4) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container1, fragment1, fragment3); |
| FragmentTestUtil.assertChildren(container2, fragment2, fragment4); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container1, fragment1); |
| FragmentTestUtil.assertChildren(container2, fragment2); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container1, fragment1); |
| FragmentTestUtil.assertChildren(container2); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| assertEquals(0, container1.getChildCount()); |
| } |
| |
| // When you add a fragment that's has already been added, it should throw. |
| @Test |
| public void doubleAdd() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment1).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| mActivityRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| try { |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment1) |
| .addToBackStack(null) |
| .commit(); |
| fm.executePendingTransactions(); |
| fail("Adding a fragment that is already added should be an error"); |
| } catch (IllegalStateException e) { |
| // expected |
| } |
| } |
| }); |
| } |
| |
| // Make sure that removed fragments remove the right Views. Popping the back stack should |
| // add the Views back properly |
| @Test |
| public void removeFragments() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| final StrictViewFragment fragment2 = new StrictViewFragment(); |
| final StrictViewFragment fragment3 = new StrictViewFragment(); |
| final StrictViewFragment fragment4 = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment1, "1") |
| .add(R.id.fragmentContainer, fragment2, "2") |
| .add(R.id.fragmentContainer, fragment3, "3") |
| .add(R.id.fragmentContainer, fragment4, "4") |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment1, fragment2, fragment3, fragment4); |
| |
| // Remove a view |
| fm.beginTransaction().remove(fragment4).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| assertEquals(3, container.getChildCount()); |
| FragmentTestUtil.assertChildren(container, fragment1, fragment2, fragment3); |
| |
| // remove another one |
| fm.beginTransaction().remove(fragment2).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment1, fragment3); |
| |
| // Now remove the remaining: |
| fm.beginTransaction() |
| .remove(fragment3) |
| .remove(fragment1) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| final Fragment replacement1 = fm.findFragmentByTag("1"); |
| final Fragment replacement3 = fm.findFragmentByTag("3"); |
| FragmentTestUtil.assertChildren(container, replacement1, replacement3); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| final Fragment replacement2 = fm.findFragmentByTag("2"); |
| FragmentTestUtil.assertChildren(container, replacement1, replacement3, replacement2); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| final Fragment replacement4 = fm.findFragmentByTag("4"); |
| FragmentTestUtil.assertChildren(container, replacement1, replacement3, replacement2, replacement4); |
| } |
| |
| // Removing a hidden fragment should remove the View and popping should bring it back hidden |
| @Test |
| public void removeHiddenView() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment1, "1").hide(fragment1).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment1); |
| assertTrue(fragment1.isHidden()); |
| |
| fm.beginTransaction().remove(fragment1).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| final Fragment replacement1 = fm.findFragmentByTag("1"); |
| FragmentTestUtil.assertChildren(container, replacement1); |
| assertTrue(replacement1.isHidden()); |
| assertEquals(View.GONE, replacement1.getView().getVisibility()); |
| } |
| |
| // Removing a detached fragment should do nothing to the View and popping should bring |
| // the Fragment back detached |
| @Test |
| public void removeDetatchedView() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment1, "1") |
| .detach(fragment1) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container); |
| assertTrue(fragment1.isDetached()); |
| |
| fm.beginTransaction().remove(fragment1).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| final Fragment replacement1 = fm.findFragmentByTag("1"); |
| FragmentTestUtil.assertChildren(container); |
| assertTrue(replacement1.isDetached()); |
| } |
| |
| // Unlike adding the same fragment twice, you should be able to add and then remove and then |
| // add the same fragment in one transaction. |
| @Test |
| public void addRemoveAdd() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment) |
| .remove(fragment) |
| .add(R.id.fragmentContainer, fragment) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container); |
| } |
| |
| // Removing a fragment that isn't in should not throw |
| @Test |
| public void removeNotThere() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction().remove(fragment).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| } |
| |
| // Hide a fragment and its View should be GONE. Then pop it and the View should be VISIBLE |
| @Test |
| public void hideFragment() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertEquals(View.VISIBLE, fragment.getView().getVisibility()); |
| |
| fm.beginTransaction().hide(fragment).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertTrue(fragment.isHidden()); |
| assertEquals(View.GONE, fragment.getView().getVisibility()); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertFalse(fragment.isHidden()); |
| assertEquals(View.VISIBLE, fragment.getView().getVisibility()); |
| } |
| |
| // Hiding a hidden fragment should not throw |
| @Test |
| public void doubleHide() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment) |
| .hide(fragment) |
| .hide(fragment) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| // should not throw |
| } |
| |
| // Hiding a non-existing fragment should not throw |
| @Test |
| public void hideUnAdded() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .hide(fragment) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| // should not throw |
| } |
| |
| // Show a hidden fragment and its View should be VISIBLE. Then pop it and the View should be |
| // GONE. |
| @Test |
| public void showFragment() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment).hide(fragment).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertTrue(fragment.isHidden()); |
| assertEquals(View.GONE, fragment.getView().getVisibility()); |
| |
| fm.beginTransaction().show(fragment).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertFalse(fragment.isHidden()); |
| assertEquals(View.VISIBLE, fragment.getView().getVisibility()); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertTrue(fragment.isHidden()); |
| assertEquals(View.GONE, fragment.getView().getVisibility()); |
| } |
| |
| // Showing a shown fragment should not throw |
| @Test |
| public void showShown() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment) |
| .show(fragment) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| // should not throw |
| } |
| |
| // Showing a non-existing fragment should not throw |
| @Test |
| public void showUnAdded() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .show(fragment) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| // should not throw |
| } |
| |
| // Detaching a fragment should remove the View from the hierarchy. Then popping it should |
| // bring it back VISIBLE |
| @Test |
| public void detachFragment() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertFalse(fragment.isDetached()); |
| assertEquals(View.VISIBLE, fragment.getView().getVisibility()); |
| |
| fm.beginTransaction().detach(fragment).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container); |
| assertTrue(fragment.isDetached()); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertFalse(fragment.isDetached()); |
| assertEquals(View.VISIBLE, fragment.getView().getVisibility()); |
| } |
| |
| // Detaching a hidden fragment should remove the View from the hierarchy. Then popping it should |
| // bring it back hidden |
| @Test |
| public void detachHiddenFragment() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment).hide(fragment).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertFalse(fragment.isDetached()); |
| assertTrue(fragment.isHidden()); |
| assertEquals(View.GONE, fragment.getView().getVisibility()); |
| |
| fm.beginTransaction().detach(fragment).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container); |
| assertTrue(fragment.isHidden()); |
| assertTrue(fragment.isDetached()); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertTrue(fragment.isHidden()); |
| assertFalse(fragment.isDetached()); |
| assertEquals(View.GONE, fragment.getView().getVisibility()); |
| } |
| |
| // Detaching a detached fragment should not throw |
| @Test |
| public void detachDetatched() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment) |
| .detach(fragment) |
| .detach(fragment) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| // should not throw |
| } |
| |
| // Detaching a non-existing fragment should not throw |
| @Test |
| public void detachUnAdded() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .detach(fragment) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| // should not throw |
| } |
| |
| // Attaching a fragment should add the View back into the hierarchy. Then popping it should |
| // remove it again |
| @Test |
| public void attachFragment() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment).detach(fragment).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container); |
| assertTrue(fragment.isDetached()); |
| |
| fm.beginTransaction().attach(fragment).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertFalse(fragment.isDetached()); |
| assertEquals(View.VISIBLE, fragment.getView().getVisibility()); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container); |
| assertTrue(fragment.isDetached()); |
| } |
| |
| // Attaching a hidden fragment should add the View as GONE the hierarchy. Then popping it should |
| // remove it again. |
| @Test |
| public void attachHiddenFragment() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment) |
| .hide(fragment) |
| .detach(fragment) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container); |
| assertTrue(fragment.isDetached()); |
| assertTrue(fragment.isHidden()); |
| |
| fm.beginTransaction().attach(fragment).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertTrue(fragment.isHidden()); |
| assertFalse(fragment.isDetached()); |
| assertEquals(View.GONE, fragment.getView().getVisibility()); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container); |
| assertTrue(fragment.isDetached()); |
| assertTrue(fragment.isHidden()); |
| } |
| |
| // Attaching an attached fragment should not throw |
| @Test |
| public void attachAttached() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment) |
| .attach(fragment) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| // should not throw an exception |
| } |
| |
| // Attaching a non-existing fragment should not throw |
| @Test |
| public void attachUnAdded() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .attach(fragment) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| // should not throw |
| } |
| |
| // Simple replace of one fragment in a container. Popping should replace it back again |
| @Test |
| public void replaceOne() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment1, "1").commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment1); |
| |
| final StrictViewFragment fragment2 = new StrictViewFragment(); |
| fm.beginTransaction() |
| .replace(R.id.fragmentContainer, fragment2) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment2); |
| assertEquals(View.VISIBLE, fragment2.getView().getVisibility()); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| Fragment replacement1 = fm.findFragmentByTag("1"); |
| assertNotNull(replacement1); |
| FragmentTestUtil.assertChildren(container, replacement1); |
| assertFalse(replacement1.isHidden()); |
| assertTrue(replacement1.isAdded()); |
| assertFalse(replacement1.isDetached()); |
| assertEquals(View.VISIBLE, replacement1.getView().getVisibility()); |
| } |
| |
| // Replace of multiple fragments in a container. Popping should replace it back again |
| @Test |
| public void replaceTwo() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| final StrictViewFragment fragment2 = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment1, "1") |
| .add(R.id.fragmentContainer, fragment2, "2") |
| .hide(fragment2) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment1, fragment2); |
| |
| final StrictViewFragment fragment3 = new StrictViewFragment(); |
| fm.beginTransaction() |
| .replace(R.id.fragmentContainer, fragment3) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment3); |
| assertEquals(View.VISIBLE, fragment3.getView().getVisibility()); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| Fragment replacement1 = fm.findFragmentByTag("1"); |
| Fragment replacement2 = fm.findFragmentByTag("2"); |
| assertNotNull(replacement1); |
| assertNotNull(replacement2); |
| FragmentTestUtil.assertChildren(container, replacement1, replacement2); |
| assertFalse(replacement1.isHidden()); |
| assertTrue(replacement1.isAdded()); |
| assertFalse(replacement1.isDetached()); |
| assertEquals(View.VISIBLE, replacement1.getView().getVisibility()); |
| |
| // fragment2 was hidden, so it should be returned hidden |
| assertTrue(replacement2.isHidden()); |
| assertTrue(replacement2.isAdded()); |
| assertFalse(replacement2.isDetached()); |
| assertEquals(View.GONE, replacement2.getView().getVisibility()); |
| } |
| |
| // Replace of empty container. Should act as add and popping should just remove the fragment |
| @Test |
| public void replaceZero() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| |
| final StrictViewFragment fragment = new StrictViewFragment(); |
| fm.beginTransaction() |
| .replace(R.id.fragmentContainer, fragment) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment); |
| assertEquals(View.VISIBLE, fragment.getView().getVisibility()); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container); |
| } |
| |
| // Replace a fragment that exists with itself |
| @Test |
| public void replaceExisting() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| final StrictViewFragment fragment2 = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment1, "1") |
| .add(R.id.fragmentContainer, fragment2, "2") |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment1, fragment2); |
| |
| fm.beginTransaction() |
| .replace(R.id.fragmentContainer, fragment1) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment1); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| final Fragment replacement1 = fm.findFragmentByTag("1"); |
| final Fragment replacement2 = fm.findFragmentByTag("2"); |
| |
| assertSame(fragment1, replacement1); |
| FragmentTestUtil.assertChildren(container, replacement1, replacement2); |
| } |
| |
| // Have two replace operations in the same transaction to ensure that they |
| // don't interfere with each other |
| @Test |
| public void replaceReplace() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.double_container); |
| ViewGroup container1 = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer1); |
| ViewGroup container2 = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer2); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| final StrictViewFragment fragment2 = new StrictViewFragment(); |
| final StrictViewFragment fragment3 = new StrictViewFragment(); |
| final StrictViewFragment fragment4 = new StrictViewFragment(); |
| final StrictViewFragment fragment5 = new StrictViewFragment(); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer1, fragment1) |
| .add(R.id.fragmentContainer2, fragment2) |
| .replace(R.id.fragmentContainer1, fragment3) |
| .replace(R.id.fragmentContainer2, fragment4) |
| .replace(R.id.fragmentContainer1, fragment5) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| assertChildren(container1, fragment5); |
| assertChildren(container2, fragment4); |
| |
| fm.popBackStack(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| assertChildren(container1); |
| assertChildren(container2); |
| } |
| |
| // Test to prevent regressions in FragmentManager fragment replace method. See b/24693644 |
| @Test |
| public void testReplaceFragment() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| StrictViewFragment fragmentA = new StrictViewFragment(); |
| fragmentA.setLayoutId(R.layout.text_a); |
| |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragmentA) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| assertNotNull(findViewById(R.id.textA)); |
| assertNull(findViewById(R.id.textB)); |
| assertNull(findViewById(R.id.textC)); |
| |
| StrictViewFragment fragmentB = new StrictViewFragment(); |
| fragmentB.setLayoutId(R.layout.text_b); |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragmentB) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| assertNotNull(findViewById(R.id.textA)); |
| assertNotNull(findViewById(R.id.textB)); |
| assertNull(findViewById(R.id.textC)); |
| |
| StrictViewFragment fragmentC = new StrictViewFragment(); |
| fragmentC.setLayoutId(R.layout.text_c); |
| fm.beginTransaction() |
| .replace(R.id.fragmentContainer, fragmentC) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| assertNull(findViewById(R.id.textA)); |
| assertNull(findViewById(R.id.textB)); |
| assertNotNull(findViewById(R.id.textC)); |
| } |
| |
| // Test that adding a fragment with invisible or gone views does not end up with the view |
| // being visible |
| @Test |
| public void addInvisibleAndGoneFragments() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| |
| final StrictViewFragment fragment1 = new InvisibleFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment1).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment1); |
| |
| assertEquals(View.INVISIBLE, fragment1.getView().getVisibility()); |
| |
| final InvisibleFragment fragment2 = new InvisibleFragment(); |
| fragment2.visibility = View.GONE; |
| fm.beginTransaction() |
| .replace(R.id.fragmentContainer, fragment2) |
| .addToBackStack(null) |
| .commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment2); |
| |
| assertEquals(View.GONE, fragment2.getView().getVisibility()); |
| } |
| |
| // Test to ensure that popping and adding a fragment properly track the fragments added |
| // and removed. |
| @Test |
| public void popAdd() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| |
| // One fragment with a view |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| fm.beginTransaction().add(R.id.fragmentContainer, fragment1).addToBackStack(null).commit(); |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| FragmentTestUtil.assertChildren(container, fragment1); |
| |
| final StrictViewFragment fragment2 = new StrictViewFragment(); |
| final StrictViewFragment fragment3 = new StrictViewFragment(); |
| mActivityRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| fm.popBackStack(); |
| fm.beginTransaction() |
| .replace(R.id.fragmentContainer, fragment2) |
| .addToBackStack(null) |
| .commit(); |
| fm.executePendingTransactions(); |
| fm.popBackStack(); |
| fm.beginTransaction() |
| .replace(R.id.fragmentContainer, fragment3) |
| .addToBackStack(null) |
| .commit(); |
| fm.executePendingTransactions(); |
| } |
| }); |
| FragmentTestUtil.assertChildren(container, fragment3); |
| } |
| |
| // Ensure that ordered transactions are executed individually rather than together. |
| // This forces references from one fragment to another that should be executed earlier |
| // to work. |
| @Test |
| public void orderedOperationsTogether() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| |
| final StrictViewFragment fragment1 = new StrictViewFragment(); |
| fragment1.setLayoutId(R.layout.scene1); |
| final StrictViewFragment fragment2 = new StrictViewFragment(); |
| fragment2.setLayoutId(R.layout.text_a); |
| |
| mActivityRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment1) |
| .setReorderingAllowed(false) |
| .addToBackStack(null) |
| .commit(); |
| fm.beginTransaction() |
| .add(R.id.squareContainer, fragment2) |
| .setReorderingAllowed(false) |
| .addToBackStack(null) |
| .commit(); |
| fm.executePendingTransactions(); |
| } |
| }); |
| FragmentTestUtil.assertChildren(container, fragment1); |
| assertNotNull(findViewById(R.id.textA)); |
| } |
| |
| // Ensure that there is no problem if the child fragment manager is used before |
| // the View has been added. |
| @Test |
| public void childFragmentManager() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| |
| final StrictViewFragment fragment1 = new ParentFragment(); |
| fragment1.setLayoutId(R.layout.double_container); |
| |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment1) |
| .addToBackStack(null) |
| .commit(); |
| |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.assertChildren(container, fragment1); |
| ViewGroup innerContainer = (ViewGroup) |
| fragment1.getView().findViewById(R.id.fragmentContainer1); |
| |
| Fragment fragment2 = fragment1.getChildFragmentManager().findFragmentByTag("inner"); |
| FragmentTestUtil.assertChildren(innerContainer, fragment2); |
| } |
| |
| // Popping the backstack with ordered fragments should execute the operations together. |
| // When a non-backstack fragment will be raised, it should not be destroyed. |
| @Test |
| public void popToNonBackStackFragment() throws Throwable { |
| FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container); |
| final FragmentManager fm = mActivityRule.getActivity().getFragmentManager(); |
| |
| final SimpleViewFragment fragment1 = new SimpleViewFragment(); |
| |
| fm.beginTransaction() |
| .add(R.id.fragmentContainer, fragment1) |
| .commit(); |
| |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| final SimpleViewFragment fragment2 = new SimpleViewFragment(); |
| |
| fm.beginTransaction() |
| .replace(R.id.fragmentContainer, fragment2) |
| .addToBackStack("two") |
| .commit(); |
| |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| final SimpleViewFragment fragment3 = new SimpleViewFragment(); |
| |
| fm.beginTransaction() |
| .replace(R.id.fragmentContainer, fragment3) |
| .addToBackStack("three") |
| .commit(); |
| |
| FragmentTestUtil.executePendingTransactions(mActivityRule); |
| |
| FragmentTestUtil.popBackStackImmediate(mActivityRule, "two", |
| FragmentManager.POP_BACK_STACK_INCLUSIVE); |
| |
| ViewGroup container = (ViewGroup) |
| mActivityRule.getActivity().findViewById(R.id.fragmentContainer); |
| |
| FragmentTestUtil.assertChildren(container, fragment1); |
| assertEquals(2, fragment1.onCreateViewCount); |
| assertEquals(1, fragment2.onCreateViewCount); |
| assertEquals(1, fragment3.onCreateViewCount); |
| } |
| |
| private View findViewById(int viewId) { |
| return mActivityRule.getActivity().findViewById(viewId); |
| } |
| |
| private void assertChildren(ViewGroup container, Fragment... fragments) { |
| final int numFragments = fragments == null ? 0 : fragments.length; |
| assertEquals("There aren't the correct number of fragment Views in its container", |
| numFragments, container.getChildCount()); |
| for (int i = 0; i < numFragments; i++) { |
| assertEquals("Wrong Fragment View order for [" + i + "]", container.getChildAt(i), |
| fragments[i].getView()); |
| } |
| } |
| |
| public static class InvisibleFragment extends StrictViewFragment { |
| public int visibility = View.INVISIBLE; |
| |
| @Override |
| public void onViewCreated(View view, Bundle savedInstanceState) { |
| view.setVisibility(visibility); |
| super.onViewCreated(view, savedInstanceState); |
| } |
| } |
| |
| public static class ParentFragment extends StrictViewFragment { |
| public ParentFragment() { |
| setLayoutId(R.layout.double_container); |
| } |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| View view = super.onCreateView(inflater, container, savedInstanceState); |
| final StrictViewFragment fragment2 = new StrictViewFragment(); |
| fragment2.setLayoutId(R.layout.text_a); |
| |
| getChildFragmentManager().beginTransaction() |
| .add(R.id.fragmentContainer1, fragment2, "inner") |
| .addToBackStack(null) |
| .commit(); |
| getChildFragmentManager().executePendingTransactions(); |
| return view; |
| } |
| } |
| |
| public static class SimpleViewFragment extends Fragment { |
| public int onCreateViewCount; |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| onCreateViewCount++; |
| return inflater.inflate(R.layout.text_a, container, false); |
| } |
| } |
| } |