diff --git a/turbo/src/main/assets/json/test-configuration.json b/turbo/src/main/assets/json/test-configuration.json index bb1591a6..3cbeabaf 100644 --- a/turbo/src/main/assets/json/test-configuration.json +++ b/turbo/src/main/assets/json/test-configuration.json @@ -52,6 +52,14 @@ "title": "Image Viewer" } }, + { + "patterns": [ + "/custom/recede" + ], + "properties": { + "presentation": "pop" + } + }, { "patterns": [ "/custom/refresh" diff --git a/turbo/src/main/kotlin/dev/hotwire/turbo/nav/TurboNavRule.kt b/turbo/src/main/kotlin/dev/hotwire/turbo/nav/TurboNavRule.kt index 5003a44a..7a44db0d 100644 --- a/turbo/src/main/kotlin/dev/hotwire/turbo/nav/TurboNavRule.kt +++ b/turbo/src/main/kotlin/dev/hotwire/turbo/nav/TurboNavRule.kt @@ -53,9 +53,15 @@ internal class TurboNavRule( } private fun newPresentation(): TurboNavPresentation { - // Use the custom presentation provided in the path configuration + // Check if we should use the custom presentation provided in the path configuration if (newProperties.presentation != TurboNavPresentation.DEFAULT) { - return newProperties.presentation + return if (isAtStartDestination && newProperties.presentation == TurboNavPresentation.POP) { + // You cannot pop from the start destination, prevent visit + TurboNavPresentation.NONE + } else { + // Use the custom presentation + newProperties.presentation + } } val locationIsCurrent = locationsAreSame(newLocation, currentLocation) diff --git a/turbo/src/test/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationRepositoryTest.kt b/turbo/src/test/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationRepositoryTest.kt index db45b009..7aa69158 100644 --- a/turbo/src/test/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationRepositoryTest.kt +++ b/turbo/src/test/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationRepositoryTest.kt @@ -51,7 +51,7 @@ class TurboPathConfigurationRepositoryTest : BaseRepositoryTest() { assertThat(json).isNotNull() val config = load(json) - assertThat(config?.rules?.size).isEqualTo(8) + assertThat(config?.rules?.size).isEqualTo(9) } @Test diff --git a/turbo/src/test/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationTest.kt b/turbo/src/test/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationTest.kt index 6a68e609..c6c8efdb 100644 --- a/turbo/src/test/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationTest.kt +++ b/turbo/src/test/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationTest.kt @@ -38,7 +38,7 @@ class TurboPathConfigurationTest : BaseRepositoryTest() { @Test fun assetConfigurationIsLoaded() { - assertThat(pathConfiguration.rules.size).isEqualTo(8) + assertThat(pathConfiguration.rules.size).isEqualTo(9) } @Test diff --git a/turbo/src/test/kotlin/dev/hotwire/turbo/nav/TurboNavRuleTest.kt b/turbo/src/test/kotlin/dev/hotwire/turbo/nav/TurboNavRuleTest.kt index e3883100..ee784d72 100644 --- a/turbo/src/test/kotlin/dev/hotwire/turbo/nav/TurboNavRuleTest.kt +++ b/turbo/src/test/kotlin/dev/hotwire/turbo/nav/TurboNavRuleTest.kt @@ -34,6 +34,7 @@ class TurboNavRuleTest { private val featureUrl = "https://hotwired.dev/feature" private val newUrl = "https://hotwired.dev/feature/new" private val editUrl = "https://hotwired.dev/feature/edit" + private val recedeUrl = "https://hotwired.dev/custom/recede" private val refreshUrl = "https://hotwired.dev/custom/refresh" private val resumeUrl = "https://hotwired.dev/custom/resume" private val modalRootUrl = "https://hotwired.dev/custom/modal" @@ -330,6 +331,28 @@ class TurboNavRuleTest { assertThat(rule.newNavOptions).isEqualTo(navOptions) } + @Test + fun `prevent pop presentation from start destination`() { + val rule = getNavigatorRule(recedeUrl) + + // Current destination + assertThat(rule.previousLocation).isNull() + assertThat(rule.currentLocation).isEqualTo(homeUrl) + assertThat(rule.currentPresentationContext).isEqualTo(TurboNavPresentationContext.DEFAULT) + assertThat(rule.isAtStartDestination).isTrue() + + // New destination + assertThat(rule.newLocation).isEqualTo(recedeUrl) + assertThat(rule.newPresentationContext).isEqualTo(TurboNavPresentationContext.DEFAULT) + assertThat(rule.newPresentation).isEqualTo(TurboNavPresentation.NONE) + assertThat(rule.newQueryStringPresentation).isEqualTo(TurboNavQueryStringPresentation.DEFAULT) + assertThat(rule.newNavigationMode).isEqualTo(TurboNavMode.NONE) + assertThat(rule.newModalResult).isNull() + assertThat(rule.newDestinationUri).isEqualTo(webUri) + assertThat(rule.newDestination).isNotNull() + assertThat(rule.newNavOptions).isEqualTo(navOptions) + } + private fun getNavigatorRule( location: String, visitOptions: TurboVisitOptions = TurboVisitOptions(),