fix(android): add tests for backstack and fix deeplink navigation
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
*/
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
import dev.msfjarvis.claw.gradle.addTestDependencies
|
||||
|
||||
plugins {
|
||||
id("dev.msfjarvis.claw.android-application")
|
||||
id("dev.msfjarvis.claw.rename-artifacts")
|
||||
@@ -118,4 +120,6 @@ dependencies {
|
||||
compileOnly(libs.androidx.compose.glance.preview)
|
||||
|
||||
runtimeOnly(libs.androidx.profileinstaller)
|
||||
|
||||
addTestDependencies(project)
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ class MainActivity(
|
||||
windowSizeClass = windowSizeClass,
|
||||
setWebUri = { url -> webUri = url },
|
||||
deepLinkDestination = deepLinkDestination,
|
||||
clearDeepLink = { deepLinkDestination = null },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+17
-10
@@ -8,6 +8,7 @@ package dev.msfjarvis.claw.android.ui.screens
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.LocalActivity
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.EnterTransition
|
||||
import androidx.compose.animation.ExitTransition
|
||||
@@ -87,6 +88,7 @@ fun LobstersPostsScreen(
|
||||
setWebUri: (String?) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
deepLinkDestination: NavKey? = null,
|
||||
clearDeepLink: () -> Unit = {},
|
||||
viewModel: ClawViewModel = metroViewModel(),
|
||||
tagFilterViewModel: TagFilterViewModel = metroViewModel(key = "tag_filter"),
|
||||
) {
|
||||
@@ -113,7 +115,8 @@ fun LobstersPostsScreen(
|
||||
|
||||
LaunchedEffect(deepLinkDestination) {
|
||||
if (deepLinkDestination != null) {
|
||||
navigateTo(backStack, deepLinkDestination)
|
||||
navigateTo(backStack, deepLinkDestination, allowStacking = true)
|
||||
clearDeepLink()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,7 +299,8 @@ fun LobstersPostsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateTo(
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
fun navigateTo(
|
||||
backStack: MutableList<NavKey>,
|
||||
destination: NavKey,
|
||||
allowStacking: Boolean = false,
|
||||
@@ -306,24 +310,27 @@ private fun navigateTo(
|
||||
if (destination != Hottest) {
|
||||
backStack.add(Hottest)
|
||||
}
|
||||
backStack.add(destination)
|
||||
return
|
||||
}
|
||||
|
||||
if (destination is NonStackable) {
|
||||
if (allowStacking && destination is Comments) {
|
||||
val lastItem = backStack.lastOrNull()
|
||||
if (lastItem is Comments && lastItem.postId == destination.postId) {
|
||||
return
|
||||
}
|
||||
backStack.add(destination)
|
||||
return
|
||||
}
|
||||
|
||||
val existingEntry =
|
||||
backStack.firstOrNull {
|
||||
it is NonStackable && it::class.java.isAssignableFrom(destination::class.java)
|
||||
}
|
||||
|
||||
if (existingEntry != null) {
|
||||
val existingIndex = backStack.indexOf(existingEntry)
|
||||
backStack.remove(existingEntry)
|
||||
|
||||
if (allowStacking && destination is Comments && existingEntry is Comments) {
|
||||
if (destination.postId != existingEntry.postId) {
|
||||
backStack.add(existingIndex, destination)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright © Harsh Shandilya.
|
||||
* Use of this source code is governed by an MIT-style
|
||||
* license that can be found in the LICENSE file or at
|
||||
* https://opensource.org/licenses/MIT.
|
||||
*/
|
||||
package dev.msfjarvis.claw.android.ui.screens
|
||||
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import dev.msfjarvis.claw.android.ui.navigation.Comments
|
||||
import dev.msfjarvis.claw.android.ui.navigation.Hottest
|
||||
import dev.msfjarvis.claw.android.ui.navigation.Newest
|
||||
import dev.msfjarvis.claw.android.ui.navigation.Saved
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class BackStackBehaviorTest {
|
||||
|
||||
private fun makeBackStack(vararg keys: NavKey) = mutableListOf(*keys)
|
||||
|
||||
@Test
|
||||
fun `navigating from between top level destinations prevents stacking`() {
|
||||
val backStack = makeBackStack(Hottest)
|
||||
|
||||
navigateTo(backStack, Newest)
|
||||
|
||||
assertThat(backStack).containsExactly(Hottest, Newest).inOrder()
|
||||
|
||||
navigateTo(backStack, Saved)
|
||||
|
||||
assertThat(backStack).containsExactly(Hottest, Saved).inOrder()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NonStackable destinations do not stack by default`() {
|
||||
val backStack = makeBackStack(Hottest, Comments("abc123"))
|
||||
|
||||
navigateTo(backStack, Comments("def456"))
|
||||
|
||||
assertThat(backStack).containsExactly(Hottest, Comments("def456")).inOrder()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `NonStackable destinations stack when allowStacking = true`() {
|
||||
val backStack = makeBackStack(Hottest, Comments("abc123"))
|
||||
|
||||
navigateTo(backStack, Comments("def456"), allowStacking = true)
|
||||
|
||||
assertThat(backStack).containsExactly(Hottest, Comments("abc123"), Comments("def456")).inOrder()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Same destination cannot be stacked on itself`() {
|
||||
val backStack = makeBackStack(Hottest, Comments("abc123"))
|
||||
|
||||
navigateTo(backStack, Comments("abc123"), allowStacking = true)
|
||||
|
||||
assertThat(backStack).containsExactly(Hottest, Comments("abc123")).inOrder()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Same destination can be stacked with a gap in between`() {
|
||||
val backStack = makeBackStack(Hottest, Comments("abc123"), Comments("def456"))
|
||||
|
||||
navigateTo(backStack, Comments("abc123"), allowStacking = true)
|
||||
|
||||
assertThat(backStack)
|
||||
.containsExactly(Hottest, Comments("abc123"), Comments("def456"), Comments("abc123"))
|
||||
.inOrder()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user