diff --git a/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/NavigatorTest.kt b/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/NavigatorTest.kt index b08cb2a8..b825de78 100644 --- a/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/NavigatorTest.kt +++ b/karibu-testing-v10/kt10-tests/src/main/kotlin/com/github/mvysny/kaributesting/v10/NavigatorTest.kt @@ -15,9 +15,11 @@ import com.vaadin.flow.component.notification.Notification import com.vaadin.flow.component.orderedlayout.VerticalLayout import com.vaadin.flow.router.BeforeLeaveEvent import com.vaadin.flow.router.BeforeLeaveObserver +import com.vaadin.flow.router.NotFoundException import com.vaadin.flow.router.Route import com.vaadin.flow.server.VaadinRequest import com.vaadin.flow.server.auth.NavigationAccessControl +import java.io.Serializable import java.security.Principal import java.util.function.Predicate import kotlin.test.expect @@ -215,10 +217,28 @@ internal fun DynaNodeGroup.navigatorTest() { } group("security") { - test("when access is rejected, redirect goes to WelcomeView") { - UI.getCurrent().addBeforeEnterListener(NoUserLoggedInNavigationAccessControl()) - navigateTo() - expectView() + group("no user logged in") { + test("when access is rejected, redirect goes to WelcomeView") { + UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl().apply { + setLoginView(WelcomeView::class.java) + }) + navigateTo() + expectView() + } + test("when access is rejected and no login view is set, redirects to MockRouteNotFoundError") { + UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl()) + expectThrows("No route found for 'testing': Consider adding one of the following annotations to make the view accessible: @AnonymousAllowed, @PermitAll, @RolesAllowed.") { + navigateTo() + } + } + } + group("user logged in") { + test("when access is rejected, default handler redirects to MockRouteNotFoundError") { + UI.getCurrent().addBeforeEnterListener(SimpleNavigationAccessControl("admin")) + expectThrows("No route found for 'testing': Consider adding one of the following annotations to make the view accessible: @AnonymousAllowed, @PermitAll, @RolesAllowed.") { + navigateTo() + } + } } } } @@ -239,10 +259,11 @@ class NavigationPostponeView : VerticalLayout(), BeforeLeaveObserver { } } -class NoUserLoggedInNavigationAccessControl : NavigationAccessControl() { - init { - loginView = WelcomeView::class.java - } - override fun getPrincipal(request: VaadinRequest?): Principal? = null +class SimpleNavigationAccessControl(val user: String? = null) : NavigationAccessControl() { + override fun getPrincipal(request: VaadinRequest?): Principal? = if (user == null) null else SimplePrincipal(user) override fun getRolesChecker(request: VaadinRequest?): Predicate = Predicate { false } } + +data class SimplePrincipal(private val name: String): Principal, Serializable { + override fun getName(): String = name +} diff --git a/karibu-testing-v10/src/main/kotlin/com/github/mvysny/kaributesting/v10/Routes.kt b/karibu-testing-v10/src/main/kotlin/com/github/mvysny/kaributesting/v10/Routes.kt index c74996ed..2b1b95d0 100644 --- a/karibu-testing-v10/src/main/kotlin/com/github/mvysny/kaributesting/v10/Routes.kt +++ b/karibu-testing-v10/src/main/kotlin/com/github/mvysny/kaributesting/v10/Routes.kt @@ -5,6 +5,7 @@ import com.vaadin.flow.component.Component import com.vaadin.flow.component.Tag import com.vaadin.flow.router.* import com.vaadin.flow.server.VaadinContext +import com.vaadin.flow.server.auth.AnonymousAllowed import com.vaadin.flow.server.startup.ApplicationRouteRegistry import com.vaadin.flow.server.startup.RouteRegistryInitializer import io.github.classgraph.ClassGraph @@ -110,6 +111,7 @@ public fun ApplicationRouteRegistry.clearPwaClass() { * any navigation to a missing route and can respond with an informative exception. */ @Tag(Tag.DIV) +@AnonymousAllowed public open class MockRouteNotFoundError: Component(), HasErrorParameter { override fun setErrorParameter(event: BeforeEnterEvent, parameter: ErrorParameter): Int { val message: String = buildString {