1 /* 2 * Copyright (C) 2017 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 18 19 import android.app.Instrumentation 20 import android.content.Context 21 import android.net.Uri 22 import androidx.navigation.test.R 23 import androidx.navigation.test.TestEnum 24 import androidx.test.core.app.ApplicationProvider 25 import androidx.test.ext.junit.runners.AndroidJUnit4 26 import androidx.test.filters.SmallTest 27 import androidx.test.platform.app.InstrumentationRegistry 28 import androidx.testutils.TestNavigatorProvider 29 import com.google.common.truth.Truth.assertThat 30 import org.junit.Before 31 import org.junit.Test 32 import org.junit.runner.RunWith 33 34 @SmallTest 35 @RunWith(AndroidJUnit4::class) 36 class NavInflaterTest { 37 private lateinit var instrumentation: Instrumentation 38 39 @Before getInstrumentationnull40 fun getInstrumentation() { 41 instrumentation = InstrumentationRegistry.getInstrumentation() 42 } 43 44 @Test testInflateSimplenull45 fun testInflateSimple() { 46 val context = ApplicationProvider.getApplicationContext() as Context 47 val navInflater = NavInflater(context, TestNavigatorProvider()) 48 val graph = navInflater.inflate(R.navigation.nav_simple) 49 50 assertThat(graph).isNotNull() 51 assertThat(graph.startDestinationId).isEqualTo(R.id.start_test) 52 } 53 54 @Test testEmptyLabelnull55 fun testEmptyLabel() { 56 val context = ApplicationProvider.getApplicationContext() as Context 57 val navInflater = NavInflater(context, TestNavigatorProvider()) 58 val graph = navInflater.inflate(R.navigation.nav_simple) 59 60 assertThat(graph).isNotNull() 61 assertThat(graph.label).isEqualTo("") 62 } 63 64 @Test(expected = RuntimeException::class) testInflateInvalidArgumentArgTypenull65 fun testInflateInvalidArgumentArgType() { 66 val context = ApplicationProvider.getApplicationContext() as Context 67 val navInflater = NavInflater(context, TestNavigatorProvider()) 68 navInflater.inflate(R.navigation.nav_invalid_argument_arg_type) 69 } 70 71 @Test(expected = RuntimeException::class) testInflateInvalidArgumentDefaultValuenull72 fun testInflateInvalidArgumentDefaultValue() { 73 val context = ApplicationProvider.getApplicationContext() as Context 74 val navInflater = NavInflater(context, TestNavigatorProvider()) 75 navInflater.inflate(R.navigation.nav_invalid_argument_default_value) 76 } 77 78 @Test testInflateDeepLinkWithApplicationIdnull79 fun testInflateDeepLinkWithApplicationId() { 80 val context = ApplicationProvider.getApplicationContext() as Context 81 val navInflater = NavInflater(context, TestNavigatorProvider()) 82 val graph = navInflater.inflate(R.navigation.nav_simple) 83 84 assertThat(graph).isNotNull() 85 val expectedUri = 86 Uri.parse("android-app://" + instrumentation.targetContext.packageName + "/test/arg2") 87 val expectedDeepLinkRequest = NavDeepLinkRequest.Builder.fromUri(expectedUri).build() 88 val result = graph.matchDeepLink(expectedDeepLinkRequest) 89 assertThat(result).isNotNull() 90 assertThat(result?.destination).isNotNull() 91 assertThat(result?.destination?.id).isEqualTo(R.id.second_test) 92 } 93 94 @Test testInflateDeepLinkWithApplicationIdActionnull95 fun testInflateDeepLinkWithApplicationIdAction() { 96 val context = ApplicationProvider.getApplicationContext() as Context 97 val navInflater = NavInflater(context, TestNavigatorProvider()) 98 val graph = navInflater.inflate(R.navigation.nav_deeplink) 99 100 assertThat(graph).isNotNull() 101 val expectedDeepLinkRequest = NavDeepLinkRequest.Builder.fromAction("action.only").build() 102 val result = graph.matchDeepLink(expectedDeepLinkRequest) 103 assertThat(result).isNotNull() 104 assertThat(result?.destination).isNotNull() 105 assertThat(result?.destination?.id).isEqualTo(R.id.action_only) 106 } 107 108 @Test testInflateDeepLinkWithApplicationIdAction_nonNullableArgnull109 fun testInflateDeepLinkWithApplicationIdAction_nonNullableArg() { 110 val context = ApplicationProvider.getApplicationContext() as Context 111 val navInflater = NavInflater(context, TestNavigatorProvider()) 112 val graph = navInflater.inflate(R.navigation.nav_simple) 113 114 assertThat(graph).isNotNull() 115 val expectedDeepLinkRequest = NavDeepLinkRequest.Builder.fromAction("test.action2").build() 116 val result = graph.matchDeepLink(expectedDeepLinkRequest) 117 assertThat(result).isNull() 118 } 119 120 @Test testInflateDeepLinkWithApplicationIdEmptyActionnull121 fun testInflateDeepLinkWithApplicationIdEmptyAction() { 122 val context = ApplicationProvider.getApplicationContext() as Context 123 val navInflater = NavInflater(context, TestNavigatorProvider()) 124 val graph = navInflater.inflate(R.navigation.nav_simple) 125 126 assertThat(graph).isNotNull() 127 val expectedDeepLinkRequest = 128 NavDeepLinkRequest.Builder.fromUri( 129 Uri.parse( 130 "android-app://" + 131 instrumentation.targetContext.packageName + 132 "/test/param1/param2" 133 ) 134 ) 135 .build() 136 val result = graph.matchDeepLink(expectedDeepLinkRequest) 137 assertThat(result).isNotNull() 138 assertThat(result?.destination).isNotNull() 139 assertThat(result?.destination?.id).isEqualTo(R.id.second_test) 140 } 141 142 @Test testInflateDeepLinkWithApplicationIdMimeTypenull143 fun testInflateDeepLinkWithApplicationIdMimeType() { 144 val context = ApplicationProvider.getApplicationContext() as Context 145 val navInflater = NavInflater(context, TestNavigatorProvider()) 146 val graph = navInflater.inflate(R.navigation.nav_deeplink) 147 148 assertThat(graph).isNotNull() 149 val expectedDeepLinkRequest = NavDeepLinkRequest.Builder.fromMimeType("mime/only").build() 150 val result = graph.matchDeepLink(expectedDeepLinkRequest) 151 assertThat(result).isNotNull() 152 assertThat(result?.destination).isNotNull() 153 assertThat(result?.destination?.id).isEqualTo(R.id.mime_only) 154 } 155 156 @Test testInflateDeepLinkWithApplicationIdMimeTypeAndUri_nonNullableArgMissingUrinull157 fun testInflateDeepLinkWithApplicationIdMimeTypeAndUri_nonNullableArgMissingUri() { 158 val context = ApplicationProvider.getApplicationContext() as Context 159 val navInflater = NavInflater(context, TestNavigatorProvider()) 160 val graph = navInflater.inflate(R.navigation.nav_simple) 161 162 assertThat(graph).isNotNull() 163 val expectedDeepLinkRequest = NavDeepLinkRequest.Builder.fromMimeType("type/test2").build() 164 val result = graph.matchDeepLink(expectedDeepLinkRequest) 165 assertThat(result).isNull() 166 } 167 168 @Test testInflateDeepLinkWithApplicationIdMimeTypeAndActionnull169 fun testInflateDeepLinkWithApplicationIdMimeTypeAndAction() { 170 val context = ApplicationProvider.getApplicationContext() as Context 171 val navInflater = NavInflater(context, TestNavigatorProvider()) 172 val graph = navInflater.inflate(R.navigation.nav_deeplink) 173 174 assertThat(graph).isNotNull() 175 val expectedDeepLinkRequest = 176 NavDeepLinkRequest.Builder.fromMimeType("mime/action").setAction("mime.action").build() 177 val result = graph.matchDeepLink(expectedDeepLinkRequest) 178 assertThat(result).isNotNull() 179 assertThat(result?.destination).isNotNull() 180 assertThat(result?.destination?.id).isEqualTo(R.id.mime_action) 181 } 182 183 @Test testInflateDeepLinkWithApplicationIdMimeTypeAndAction_missingUrinull184 fun testInflateDeepLinkWithApplicationIdMimeTypeAndAction_missingUri() { 185 val context = ApplicationProvider.getApplicationContext() as Context 186 val navInflater = NavInflater(context, TestNavigatorProvider()) 187 val graph = navInflater.inflate(R.navigation.nav_deeplink) 188 189 assertThat(graph).isNotNull() 190 val expectedDeepLinkRequest = 191 NavDeepLinkRequest.Builder.fromMimeType("uri/actionMime") 192 .setAction("uri.action.mime") 193 .build() 194 val result = graph.matchDeepLink(expectedDeepLinkRequest) 195 assertThat(result).isNull() 196 } 197 198 @Test testInflateDeepLinkWithApplicationIdMimeTypeAndUrinull199 fun testInflateDeepLinkWithApplicationIdMimeTypeAndUri() { 200 val context = ApplicationProvider.getApplicationContext() as Context 201 val navInflater = NavInflater(context, TestNavigatorProvider()) 202 val graph = navInflater.inflate(R.navigation.nav_deeplink) 203 204 assertThat(graph).isNotNull() 205 val expectedDeepLinkRequest = 206 NavDeepLinkRequest.Builder.fromMimeType("mime/uri") 207 .setUri( 208 Uri.parse( 209 "android-app://" + instrumentation.targetContext.packageName + "/mime/uri" 210 ) 211 ) 212 .build() 213 val result = graph.matchDeepLink(expectedDeepLinkRequest) 214 assertThat(result).isNotNull() 215 assertThat(result?.destination).isNotNull() 216 assertThat(result?.destination?.id).isEqualTo(R.id.mime_uri) 217 } 218 219 @Test testInflateDeepLinkWithApplicationIdMimeTypeAndUri_missingUrinull220 fun testInflateDeepLinkWithApplicationIdMimeTypeAndUri_missingUri() { 221 val context = ApplicationProvider.getApplicationContext() as Context 222 val navInflater = NavInflater(context, TestNavigatorProvider()) 223 val graph = navInflater.inflate(R.navigation.nav_deeplink) 224 225 assertThat(graph).isNotNull() 226 val expectedDeepLinkRequest = NavDeepLinkRequest.Builder.fromMimeType("mime/uri").build() 227 val result = graph.matchDeepLink(expectedDeepLinkRequest) 228 assertThat(result).isNull() 229 } 230 231 @Test testInflateDeepLinkWithApplicationIdActionAndUrinull232 fun testInflateDeepLinkWithApplicationIdActionAndUri() { 233 val context = ApplicationProvider.getApplicationContext() as Context 234 val navInflater = NavInflater(context, TestNavigatorProvider()) 235 val graph = navInflater.inflate(R.navigation.nav_deeplink) 236 237 assertThat(graph).isNotNull() 238 val expectedDeepLinkRequest = 239 NavDeepLinkRequest.Builder.fromAction("action.uri") 240 .setUri( 241 Uri.parse( 242 "android-app://" + instrumentation.targetContext.packageName + "/action/uri" 243 ) 244 ) 245 .build() 246 val result = graph.matchDeepLink(expectedDeepLinkRequest) 247 assertThat(result).isNotNull() 248 assertThat(result?.destination).isNotNull() 249 assertThat(result?.destination?.id).isEqualTo(R.id.action_uri) 250 } 251 252 @Test testInflateDeepLinkWithApplicationIdActionAndUri_missingActionnull253 fun testInflateDeepLinkWithApplicationIdActionAndUri_missingAction() { 254 val context = ApplicationProvider.getApplicationContext() as Context 255 val navInflater = NavInflater(context, TestNavigatorProvider()) 256 val graph = navInflater.inflate(R.navigation.nav_deeplink) 257 258 assertThat(graph).isNotNull() 259 val expectedDeepLinkRequest = 260 NavDeepLinkRequest.Builder.fromUri( 261 Uri.parse( 262 "android-app://" + instrumentation.targetContext.packageName + "/action/uri" 263 ) 264 ) 265 .build() 266 val result = graph.matchDeepLink(expectedDeepLinkRequest) 267 assertThat(result).isNull() 268 } 269 270 @Test testInflateWithDataPatternApplicationIdnull271 fun testInflateWithDataPatternApplicationId() { 272 val context = ApplicationProvider.getApplicationContext() as Context 273 val activityNavigator = ActivityNavigator(context) 274 val navInflater = 275 NavInflater(context, TestNavigatorProvider().apply { addNavigator(activityNavigator) }) 276 277 val graph = navInflater.inflate(R.navigation.nav_applicationid_arg) 278 val destination = graph.nodes.get(R.id.dataPattern_appId) as ActivityNavigator.Destination 279 280 assertThat(destination.dataPattern) 281 .isEqualTo("http://www.example.com/${context.packageName}") 282 } 283 284 @Test testInflateWithNullDataPatternnull285 fun testInflateWithNullDataPattern() { 286 val context = ApplicationProvider.getApplicationContext() as Context 287 val activityNavigator = ActivityNavigator(context) 288 val navInflater = 289 NavInflater(context, TestNavigatorProvider().apply { addNavigator(activityNavigator) }) 290 291 val graph = navInflater.inflate(R.navigation.nav_applicationid_arg) 292 val destination = graph.nodes.get(R.id.dataPattern_null) as ActivityNavigator.Destination 293 294 assertThat(destination.dataPattern).isNull() 295 } 296 297 @Test testInflateWithDataApplicationIdnull298 fun testInflateWithDataApplicationId() { 299 val context = ApplicationProvider.getApplicationContext() as Context 300 val activityNavigator = ActivityNavigator(context) 301 302 val navInflater = 303 NavInflater(context, TestNavigatorProvider().apply { addNavigator(activityNavigator) }) 304 305 val graph = navInflater.inflate(R.navigation.nav_applicationid_arg) 306 val destination = graph.nodes.get(R.id.data_appId) as ActivityNavigator.Destination 307 308 assertThat(destination.data) 309 .isEqualTo(Uri.parse("http://www.example.com/${context.packageName}")) 310 } 311 312 @Test testInflateWithNullDatanull313 fun testInflateWithNullData() { 314 val context = ApplicationProvider.getApplicationContext() as Context 315 val activityNavigator = ActivityNavigator(context) 316 val navInflater = 317 NavInflater(context, TestNavigatorProvider().apply { addNavigator(activityNavigator) }) 318 319 val graph = navInflater.inflate(R.navigation.nav_applicationid_arg) 320 val destination = graph.nodes.get(R.id.data_null) as ActivityNavigator.Destination 321 322 assertThat(destination.data).isNull() 323 } 324 325 @Test testDefaultArgumentsIntegernull326 fun testDefaultArgumentsInteger() { 327 val defaultArguments = inflateDefaultArgumentsFromGraph() 328 329 assertThat(defaultArguments["test_int"]?.run { type to defaultValue }) 330 .isEqualTo(NavType.IntType to 12) 331 } 332 333 @Test testDefaultArgumentsFloatnull334 fun testDefaultArgumentsFloat() { 335 val defaultArguments = inflateDefaultArgumentsFromGraph() 336 337 assertThat(defaultArguments["test_float"]?.run { type to defaultValue }) 338 .isEqualTo(NavType.FloatType to 3.14f) 339 } 340 341 @Test testDefaultIntArgumentsFloatnull342 fun testDefaultIntArgumentsFloat() { 343 val defaultArguments = inflateDefaultArgumentsFromGraph() 344 345 assertThat(defaultArguments["test_int_as_float"]?.run { type to defaultValue }) 346 .isEqualTo(NavType.FloatType to 3f) 347 } 348 349 @Test testDefaultArgumentsBooleannull350 fun testDefaultArgumentsBoolean() { 351 val defaultArguments = inflateDefaultArgumentsFromGraph() 352 353 assertThat(defaultArguments["test_boolean"]?.run { type to defaultValue }) 354 .isEqualTo(NavType.BoolType to true) 355 assertThat(defaultArguments["test_boolean_false"]?.run { type to defaultValue }) 356 .isEqualTo(NavType.BoolType to false) 357 assertThat(defaultArguments["test_boolean_with_argType"]?.run { type to defaultValue }) 358 .isEqualTo(NavType.BoolType to true) 359 assertThat( 360 defaultArguments["test_boolean_with_argType_false"]?.run { type to defaultValue } 361 ) 362 .isEqualTo(NavType.BoolType to false) 363 } 364 365 @Test testDefaultArgumentsLongnull366 fun testDefaultArgumentsLong() { 367 val defaultArguments = inflateDefaultArgumentsFromGraph() 368 369 assertThat(defaultArguments["test_long"]?.run { type to defaultValue }) 370 .isEqualTo(NavType.LongType to 456789013456L) 371 assertThat(defaultArguments["test_long_with_argType"]?.run { type to defaultValue }) 372 .isEqualTo(NavType.LongType to 456789013456L) 373 assertThat(defaultArguments["test_long_short"]?.run { type to defaultValue }) 374 .isEqualTo(NavType.LongType to 123L) 375 } 376 377 @Test testDefaultArgumentsEnumnull378 fun testDefaultArgumentsEnum() { 379 val defaultArguments = inflateDefaultArgumentsFromGraph() 380 381 assertThat(defaultArguments["test_enum"]?.run { type to defaultValue }) 382 .isEqualTo(NavType.EnumType(TestEnum::class.java) to TestEnum.VALUE_ONE) 383 } 384 385 @Test testDefaultArgumentsStringnull386 fun testDefaultArgumentsString() { 387 val defaultArguments = inflateDefaultArgumentsFromGraph() 388 389 assertThat(defaultArguments["test_string"]?.run { type to defaultValue }) 390 .isEqualTo(NavType.StringType to "abc") 391 assertThat(defaultArguments["test_string_bool"]?.run { type to defaultValue }) 392 .isEqualTo(NavType.StringType to "true") 393 assertThat(defaultArguments["test_string_long"]?.run { type to defaultValue }) 394 .isEqualTo(NavType.StringType to "123L") 395 assertThat(defaultArguments["test_string_integer"]?.run { type to defaultValue }) 396 .isEqualTo(NavType.StringType to "123") 397 398 assertThat( 399 defaultArguments["test_string_no_default"]?.run { type to isDefaultValuePresent } 400 ) 401 .isEqualTo(NavType.StringType to false) 402 } 403 404 @Test testDefaultArgumentsStringArraynull405 fun testDefaultArgumentsStringArray() { 406 val defaultArguments = inflateDefaultArgumentsFromGraph() 407 408 assertThat(defaultArguments["test_string_array"]?.run { type to defaultValue }) 409 .isEqualTo(NavType.StringArrayType to null) 410 } 411 412 @Test testDefaultArgumentsReferencenull413 fun testDefaultArgumentsReference() { 414 val defaultArguments = inflateDefaultArgumentsFromGraph() 415 416 assertThat(defaultArguments["test_reference"]?.run { type to defaultValue }) 417 .isEqualTo(NavType.ReferenceType to R.style.AppTheme) 418 assertThat(defaultArguments["test_reference_dimen"]?.run { type to defaultValue }) 419 .isEqualTo(NavType.ReferenceType to R.dimen.test_dimen_arg) 420 assertThat(defaultArguments["test_reference_integer"]?.run { type to defaultValue }) 421 .isEqualTo(NavType.ReferenceType to R.integer.test_integer_arg) 422 assertThat(defaultArguments["test_reference_string"]?.run { type to defaultValue }) 423 .isEqualTo(NavType.ReferenceType to R.string.test_string_arg) 424 assertThat(defaultArguments["test_reference_bool"]?.run { type to defaultValue }) 425 .isEqualTo(NavType.ReferenceType to R.bool.test_bool_arg) 426 assertThat(defaultArguments["test_reference_color"]?.run { type to defaultValue }) 427 .isEqualTo(NavType.ReferenceType to R.color.test_color_arg) 428 assertThat(defaultArguments["test_reference_zero_default"]?.run { type to defaultValue }) 429 .isEqualTo(NavType.ReferenceType to 0) 430 } 431 432 @Test testRelativeClassNamenull433 fun testRelativeClassName() { 434 val defaultArguments = inflateDefaultArgumentsFromGraph() 435 assertThat(defaultArguments["test_relative_classname"]?.run { type to defaultValue }) 436 .isEqualTo(NavType.EnumType(TestEnum::class.java) to TestEnum.VALUE_TWO) 437 } 438 439 @Test 440 @Suppress("DEPRECATION") testActionArgumentsnull441 fun testActionArguments() { 442 val context = ApplicationProvider.getApplicationContext() as Context 443 val navInflater = NavInflater(context, TestNavigatorProvider()) 444 val graph = navInflater.inflate(R.navigation.nav_default_arguments) 445 val startDestination = graph.findNode(graph.startDestinationId) 446 val action = startDestination?.getAction(R.id.my_action) 447 assertThat(action?.defaultArguments?.get("test_action_arg")).isEqualTo(123L) 448 } 449 inflateDefaultArgumentsFromGraphnull450 private fun inflateDefaultArgumentsFromGraph(): Map<String, NavArgument> { 451 val context = ApplicationProvider.getApplicationContext() as Context 452 val navInflater = NavInflater(context, TestNavigatorProvider()) 453 val graph = navInflater.inflate(R.navigation.nav_default_arguments) 454 455 val startDestination = graph.findNode(graph.startDestinationId) 456 val defaultArguments = startDestination?.arguments 457 458 assertThat(defaultArguments).isNotNull() 459 return defaultArguments as Map<String, NavArgument> 460 } 461 } 462