1 /*
2  * Copyright 2020 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 package androidx.navigation.fragment
18 
19 import android.os.Bundle
20 import androidx.navigation.findNavController
21 import androidx.navigation.fragment.test.NavigationActivityMultiNavHost
22 import androidx.navigation.fragment.test.R
23 import androidx.test.core.app.ActivityScenario
24 import androidx.test.ext.junit.runners.AndroidJUnit4
25 import androidx.test.filters.MediumTest
26 import androidx.testutils.withActivity
27 import com.google.common.truth.Truth.assertThat
28 import com.google.common.truth.Truth.assertWithMessage
29 import java.util.concurrent.CountDownLatch
30 import java.util.concurrent.TimeUnit
31 import org.junit.Test
32 import org.junit.runner.RunWith
33 
34 @MediumTest
35 @RunWith(AndroidJUnit4::class)
36 class MultiNavHostFragmentTest {
37 
38     @Test
testFragmentToNavHostnull39     fun testFragmentToNavHost() {
40         with(ActivityScenario.launch(NavigationActivityMultiNavHost::class.java)) {
41             val navController = withActivity { findNavController(R.id.nav_host_fragment) }
42 
43             withActivity {
44                 navController.setGraph(R.navigation.nav_nav_host)
45                 navController.navigate(R.id.nav_host_1)
46             }
47 
48             val rootNavController = withActivity {
49                 val navHostFragment =
50                     supportFragmentManager.findFragmentById(R.id.nav_host_fragment)!!
51                 navHostFragment.requireView().findNavController()
52             }
53             assertWithMessage("Child should have changed the NavController")
54                 .that(rootNavController)
55                 .isNotEqualTo(navController)
56         }
57     }
58 
59     @Test
testNavHostToFragmentnull60     fun testNavHostToFragment() {
61         with(ActivityScenario.launch(NavigationActivityMultiNavHost::class.java)) {
62             val navController = withActivity { findNavController(R.id.nav_host_fragment) }
63 
64             withActivity {
65                 navController.setGraph(R.navigation.nav_nav_host)
66                 navController.navigate(R.id.nav_host_1)
67             }
68             val childFragment = withActivity {
69                 supportFragmentManager
70                     .findFragmentById(R.id.nav_host_fragment)
71                     ?.childFragmentManager
72                     ?.findFragmentById(R.id.nav_host_fragment) as BasicNavHostFragment
73             }
74 
75             withActivity { navController.popBackStack() }
76             val returnNavController = withActivity {
77                 val navHostFragment =
78                     supportFragmentManager.findFragmentById(R.id.nav_host_fragment)!!
79                 navHostFragment.requireView().findNavController()
80             }
81 
82             assertThat(childFragment.destroyViewCountDownLatch.await(1000, TimeUnit.MILLISECONDS))
83                 .isTrue()
84 
85             assertWithMessage("NavController should not have changed")
86                 .that(returnNavController)
87                 .isSameInstanceAs(navController)
88         }
89     }
90 
91     @Test
testNavHostToNavHostnull92     fun testNavHostToNavHost() {
93         with(ActivityScenario.launch(NavigationActivityMultiNavHost::class.java)) {
94             val navController = withActivity { findNavController(R.id.nav_host_fragment) }
95 
96             withActivity {
97                 navController.setGraph(R.navigation.nav_nav_host)
98                 navController.navigate(R.id.nav_host_1)
99             }
100 
101             val firstChildNavController = withActivity {
102                 val navHostFragment =
103                     supportFragmentManager.findFragmentById(R.id.nav_host_fragment)!!
104                 navHostFragment.requireView().findNavController()
105             }
106             assertWithMessage("child should have changed the NavController")
107                 .that(firstChildNavController)
108                 .isNotEqualTo(navController)
109 
110             withActivity { navController.navigate(R.id.nav_host_2) }
111             val secondChildNavController = withActivity {
112                 val navHostFragment =
113                     supportFragmentManager.findFragmentById(R.id.nav_host_fragment)!!
114                 navHostFragment.requireView().findNavController()
115             }
116 
117             assertWithMessage("Second child should have changed the NavController")
118                 .that(secondChildNavController)
119                 .isNotEqualTo(firstChildNavController)
120 
121             assertWithMessage("the second child navHost should be different from the parent")
122                 .that(secondChildNavController)
123                 .isNotEqualTo(navController)
124         }
125     }
126 }
127 
128 class BasicNavHostFragment : NavHostFragment() {
129     val destroyViewCountDownLatch = CountDownLatch(1)
130 
onCreatenull131     override fun onCreate(savedInstanceState: Bundle?) {
132         super.onCreate(savedInstanceState)
133         navController.setGraph(R.navigation.nav_nav_host)
134     }
135 
onDestroyViewnull136     override fun onDestroyView() {
137         super.onDestroyView()
138         destroyViewCountDownLatch.countDown()
139     }
140 }
141