1f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake/* 2f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * Copyright 2018 The Android Open Source Project 3f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * 4f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * Licensed under the Apache License, Version 2.0 (the "License"); 5f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * you may not use this file except in compliance with the License. 6f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * You may obtain a copy of the License at 7f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * 8f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * http://www.apache.org/licenses/LICENSE-2.0 9f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * 10f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * Unless required by applicable law or agreed to in writing, software 11f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * distributed under the License is distributed on an "AS IS" BASIS, 12f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * See the License for the specific language governing permissions and 14f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake * limitations under the License. 15f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake */ 16f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 17f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakepackage androidx.navigation.fragment; 18f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 19f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport static org.hamcrest.CoreMatchers.equalTo; 20f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport static org.hamcrest.CoreMatchers.is; 21f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport static org.hamcrest.CoreMatchers.not; 22f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport static org.hamcrest.CoreMatchers.notNullValue; 23f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport static org.hamcrest.MatcherAssert.assertThat; 24f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 25f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport android.arch.lifecycle.Lifecycle; 26f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport android.support.test.annotation.UiThreadTest; 27f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport android.support.test.filters.SmallTest; 28f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport android.support.test.rule.ActivityTestRule; 29f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport android.support.v4.app.Fragment; 30f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport android.support.v4.app.FragmentManager; 31f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 32f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport androidx.navigation.NavOptions; 33f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport androidx.navigation.fragment.test.EmptyActivity; 34f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport androidx.navigation.fragment.test.EmptyFragment; 35f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport androidx.navigation.fragment.test.R; 36f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 37f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport org.hamcrest.CoreMatchers; 38f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport org.junit.Before; 39f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport org.junit.Rule; 40f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakeimport org.junit.Test; 41f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 42f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake@SmallTest 43f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lakepublic class FragmentNavigatorTest { 44f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 45f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake @Rule 46f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake public ActivityTestRule<EmptyActivity> mActivityRule = 47f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake new ActivityTestRule<>(EmptyActivity.class); 48f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 49f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake private EmptyActivity mEmptyActivity; 50f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake private FragmentManager mFragmentManager; 51f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 52f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake @Before 53f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake public void setup() { 54f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake mEmptyActivity = mActivityRule.getActivity(); 55f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake mFragmentManager = mEmptyActivity.getSupportFragmentManager(); 56f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake } 57f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 58f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake @UiThreadTest 59f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake @Test 60f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake public void testNavigate() { 61f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake FragmentNavigator fragmentNavigator = new FragmentNavigator(mEmptyActivity, 62f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake mFragmentManager, R.id.container); 63f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake FragmentNavigator.Destination destination = fragmentNavigator.createDestination(); 64f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake destination.setFragmentClass(EmptyFragment.class); 65f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 66f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake fragmentNavigator.navigate(destination, null, null); 67f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake mFragmentManager.executePendingTransactions(); 68f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake Fragment fragment = mFragmentManager.findFragmentById(R.id.container); 69f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Fragment should be added", fragment, is(notNullValue())); 70f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Fragment should be the correct type", fragment, 71f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake is(CoreMatchers.<Fragment>instanceOf(EmptyFragment.class))); 72f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake } 73f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 74f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake @UiThreadTest 75f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake @Test 76f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake public void testSingleTopInitial() { 77f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake FragmentNavigator fragmentNavigator = new FragmentNavigator(mEmptyActivity, 78f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake mFragmentManager, R.id.container); 79f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake FragmentNavigator.Destination destination = fragmentNavigator.createDestination(); 80f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake destination.setFragmentClass(EmptyFragment.class); 81f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 82f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake fragmentNavigator.navigate(destination, null, null); 83f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake mFragmentManager.executePendingTransactions(); 84f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake Fragment fragment = mFragmentManager.findFragmentById(R.id.container); 85f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Fragment should be added", fragment, is(notNullValue())); 86f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 87f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake fragmentNavigator.navigate(destination, null, 88f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake new NavOptions.Builder().setLaunchSingleTop(true).build()); 89f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake mFragmentManager.executePendingTransactions(); 90f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake Fragment replacementFragment = mFragmentManager.findFragmentById(R.id.container); 91f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Replacement Fragment should be added", replacementFragment, 92f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake is(notNullValue())); 93f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Replacement Fragment should be the correct type", replacementFragment, 94f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake is(CoreMatchers.<Fragment>instanceOf(EmptyFragment.class))); 95f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Replacement should be a new instance", replacementFragment, 96f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake is(not(equalTo(fragment)))); 97f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Old instance should be destroyed", fragment.getLifecycle().getCurrentState(), 98f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake is(equalTo(Lifecycle.State.DESTROYED))); 99f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake } 100f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 101f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake @UiThreadTest 102f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake @Test 103f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake public void testSingleTop() { 104f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake FragmentNavigator fragmentNavigator = new FragmentNavigator(mEmptyActivity, 105f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake mFragmentManager, R.id.container); 106f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake FragmentNavigator.Destination destination = fragmentNavigator.createDestination(); 107f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake destination.setFragmentClass(EmptyFragment.class); 108f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 109f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake // First push an initial Fragment 110f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake fragmentNavigator.navigate(destination, null, null); 111f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 112f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake // Now push the Fragment that we want to replace with a singleTop operation 113f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake fragmentNavigator.navigate(destination, null, null); 114f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake mFragmentManager.executePendingTransactions(); 115f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake Fragment fragment = mFragmentManager.findFragmentById(R.id.container); 116f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Fragment should be added", fragment, is(notNullValue())); 117f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake 118f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake fragmentNavigator.navigate(destination, null, 119f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake new NavOptions.Builder().setLaunchSingleTop(true).build()); 120f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake mFragmentManager.executePendingTransactions(); 121f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake Fragment replacementFragment = mFragmentManager.findFragmentById(R.id.container); 122f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Replacement Fragment should be added", replacementFragment, 123f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake is(notNullValue())); 124f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Replacement Fragment should be the correct type", replacementFragment, 125f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake is(CoreMatchers.<Fragment>instanceOf(EmptyFragment.class))); 126f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Replacement should be a new instance", replacementFragment, 127f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake is(not(equalTo(fragment)))); 128f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake assertThat("Old instance should be destroyed", fragment.getLifecycle().getCurrentState(), 129f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake is(equalTo(Lifecycle.State.DESTROYED))); 130f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake } 131f4e1014f8acbeb87455d04d8a1e8a38b1c16b8c3Ian Lake} 132