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