diff --git a/integration/voyager/build.gradle.kts b/integration/voyager/build.gradle.kts index bbc14f0..7c7e2f3 100644 --- a/integration/voyager/build.gradle.kts +++ b/integration/voyager/build.gradle.kts @@ -5,6 +5,7 @@ plugins { kotlin("plugin.serialization") alias(libs.plugins.jetbrains.compose) alias(libs.plugins.compose.compiler) + alias(libs.plugins.ksp) id("org.jetbrains.kotlinx.kover") alias(libs.plugins.maven.publish) } @@ -49,20 +50,25 @@ kotlin { implementation(compose.runtimeSaveable) } } + commonTest { + dependencies { + implementation(projects.ksp.coreAnnotations) + } + } - val jsMain by getting { + jsMain { dependencies { implementation(libs.serialization.json) } } - val jvmMain by getting { + jvmMain { dependsOn(commonMain.get()) dependencies { api(libs.slf4j.api) } } - val jvmTest by getting { + jvmTest { dependsOn(commonTest.get()) dependencies { implementation(libs.test.junit) @@ -71,27 +77,35 @@ kotlin { } } - val nativeMain by creating { + nativeMain { dependsOn(commonMain.get()) } - val macosMain by creating { - dependsOn(nativeMain) + macosMain { + dependsOn(nativeMain.get()) } val macosX64Main by getting { - dependsOn(macosMain) + dependsOn(macosMain.get()) } val macosArm64Main by getting { - dependsOn(macosMain) + dependsOn(macosMain.get()) } val iosX64Main by getting { - dependsOn(nativeMain) + dependsOn(nativeMain.get()) } val iosArm64Main by getting { - dependsOn(nativeMain) + dependsOn(nativeMain.get()) } val iosSimulatorArm64Main by getting { - dependsOn(nativeMain) + dependsOn(nativeMain.get()) } } } + +dependencies { + add("kspJvmTest", projects.ksp.coreProcessor) +} + +ksp { + arg("Routing_Module_Name", "Voyager") +} diff --git a/integration/voyager/common/test/dev/programadorthi/routing/voyager/Screens.kt b/integration/voyager/common/test/dev/programadorthi/routing/voyager/Screens.kt new file mode 100644 index 0000000..2a5bf92 --- /dev/null +++ b/integration/voyager/common/test/dev/programadorthi/routing/voyager/Screens.kt @@ -0,0 +1,62 @@ +package dev.programadorthi.routing.voyager + +import androidx.compose.runtime.Composable +import cafe.adriel.voyager.core.screen.Screen +import dev.programadorthi.routing.annotation.Body +import dev.programadorthi.routing.annotation.Route + +internal val invoked = mutableMapOf>() + +internal data class User( + val id: Int, + val name: String, +) + +@Route("/screen") +class Screen1 : Screen { + @Composable + override fun Content() { + invoked += "/screen" to emptyList() + } +} + +@Route("/screen-object") +object Screen2 : Screen { + @Composable + override fun Content() { + invoked += "/screen-object" to emptyList() + } +} + +@Route("/screen/{id}") +class Screen3(val id: Int) : Screen { + @Composable + override fun Content() { + invoked += "/screen/{id}" to listOf(id) + } +} + +@Route("/screen-with-name/{name}") +class Screen4(val name: String) : Screen { + private var age: Int = -1 + + @Route("/screen-with-age/{age}") + constructor(age: Int) : this("") { + this.age = age + } + + @Composable + override fun Content() { + invoked += "/screen-with-name/{name}" to listOf(name) + invoked += "/screen-with-age/{age}" to listOf(age) + } +} + +@Route("/screen-with-body") +internal class Screen5(@Body val user: User) : Screen { + + @Composable + override fun Content() { + invoked += "/screen-with-body" to listOf(user) + } +} diff --git a/integration/voyager/jvm/test/dev/programadorthi/routing/voyager/VoyagerRoutingByAnnotationsTest.kt b/integration/voyager/jvm/test/dev/programadorthi/routing/voyager/VoyagerRoutingByAnnotationsTest.kt new file mode 100644 index 0000000..a3e4708 --- /dev/null +++ b/integration/voyager/jvm/test/dev/programadorthi/routing/voyager/VoyagerRoutingByAnnotationsTest.kt @@ -0,0 +1,154 @@ +package dev.programadorthi.routing.voyager + +import dev.programadorthi.routing.core.push +import dev.programadorthi.routing.core.pushWithBody +import dev.programadorthi.routing.core.routing +import dev.programadorthi.routing.generated.configure +import dev.programadorthi.routing.voyager.helper.FakeScreen +import dev.programadorthi.routing.voyager.helper.runComposeTest +import kotlin.random.Random +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceTimeBy + +@OptIn(ExperimentalCoroutinesApi::class) +internal class VoyagerRoutingByAnnotationsTest { + + @Test + fun shouldHandleScreenClass() = + runComposeTest { coroutineContext, composition, clock -> + // GIVEN + val routing = + routing(parentCoroutineContext = coroutineContext) { + configure() + } + + composition.setContent { + VoyagerRouting( + routing = routing, + initialScreen = FakeScreen(), + ) + } + + // WHEN + routing.push("/screen") + advanceTimeBy(99) // Ask for routing + clock.sendFrame(0L) // Ask for recomposition + + // THEN + assertEquals(emptyList(), invoked.remove("/screen")) + } + + @Test + fun shouldHandleScreenObject() = + runComposeTest { coroutineContext, composition, clock -> + // GIVEN + val routing = + routing(parentCoroutineContext = coroutineContext) { + configure() + } + + composition.setContent { + VoyagerRouting( + routing = routing, + initialScreen = FakeScreen(), + ) + } + + // WHEN + routing.push("/screen-object") + advanceTimeBy(99) // Ask for routing + clock.sendFrame(0L) // Ask for recomposition + + // THEN + assertEquals(emptyList(), invoked.remove("/screen-object")) + } + + @Test + fun shouldHandleScreenWithParameter() = + runComposeTest { coroutineContext, composition, clock -> + // GIVEN + val routing = + routing(parentCoroutineContext = coroutineContext) { + configure() + } + + composition.setContent { + VoyagerRouting( + routing = routing, + initialScreen = FakeScreen(), + ) + } + + // WHEN + val nextInt = Random.Default.nextInt() + routing.push("/screen/$nextInt") + advanceTimeBy(99) // Ask for routing + clock.sendFrame(0L) // Ask for recomposition + + // THEN + assertEquals(listOf(nextInt), invoked.remove("/screen/{id}")) + } + + @Test + fun shouldHandleScreenWithMultipleConstructors() = + runComposeTest { coroutineContext, composition, clock -> + // GIVEN + val routing = + routing(parentCoroutineContext = coroutineContext) { + configure() + } + + composition.setContent { + VoyagerRouting( + routing = routing, + initialScreen = FakeScreen(), + ) + } + + // WHEN + routing.push("/screen-with-name/Routing") + advanceTimeBy(99) // Ask for routing + clock.sendFrame(0L) // Ask for recomposition + + val fromName = invoked.remove("/screen-with-name/{name}") + + routing.push("/screen-with-age/18") + advanceTimeBy(99) // Ask for routing + clock.sendFrame(0L) // Ask for recomposition + + val fromAge = invoked.remove("/screen-with-age/{age}") + + // THEN + assertEquals(listOf("Routing"), fromName) + assertEquals(listOf(18), fromAge) + } + + @Test + fun shouldHandleScreenWithBody() = + runComposeTest { coroutineContext, composition, clock -> + // GIVEN + val routing = + routing(parentCoroutineContext = coroutineContext) { + configure() + } + + composition.setContent { + VoyagerRouting( + routing = routing, + initialScreen = FakeScreen(), + ) + } + + // WHEN + val body = User(id = 456, name = "With Body") + routing.pushWithBody(path = "/screen-with-body", body = body) + advanceTimeBy(99) // Ask for routing + clock.sendFrame(0L) // Ask for recomposition + + // THEN + assertEquals(listOf(body), invoked.remove("/screen-with-body")) + } + +} diff --git a/samples/ksp-sample/build.gradle.kts b/samples/ksp-sample/build.gradle.kts deleted file mode 100644 index 4478ad3..0000000 --- a/samples/ksp-sample/build.gradle.kts +++ /dev/null @@ -1,47 +0,0 @@ -import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi - -plugins { - kotlin("multiplatform") - alias(libs.plugins.ksp) - alias(libs.plugins.routing) - alias(libs.plugins.jetbrains.compose) - alias(libs.plugins.compose.compiler) -} - -kotlin { - jvm { - @OptIn(ExperimentalKotlinGradlePluginApi::class) - mainRun { - mainClass.set("MainKt") - } - } - - sourceSets { - commonMain { - dependencies { - implementation(libs.routing.core) - implementation(libs.routing.compose) - implementation(libs.routing.voyager) - implementation(libs.routing.annotations) - implementation(compose.runtime) - } - } - } -} - -/*dependencies { - add("kspJvm", projects.ksp.coreProcessor) -} - -configurations.all { - resolutionStrategy.dependencySubstitution { - substitute(module("dev.programadorthi.routing:core")) - .using(project(":core")) - substitute(module("dev.programadorthi.routing:compose")) - .using(project(":integration:compose")) - substitute(module("dev.programadorthi.routing:voyager")) - .using(project(":integration:voyager")) - substitute(module("dev.programadorthi.routing:ksp-core-annotations")) - .using(project(":ksp:core-annotations")) - } -}*/ diff --git a/samples/ksp-sample/src/commonMain/kotlin/dev/programadorthi/routing/sample/Screens.kt b/samples/ksp-sample/src/commonMain/kotlin/dev/programadorthi/routing/sample/Screens.kt deleted file mode 100644 index 8e00195..0000000 --- a/samples/ksp-sample/src/commonMain/kotlin/dev/programadorthi/routing/sample/Screens.kt +++ /dev/null @@ -1,41 +0,0 @@ -package dev.programadorthi.routing.sample - -import androidx.compose.runtime.Composable -import cafe.adriel.voyager.core.screen.Screen -import dev.programadorthi.routing.annotation.Body -import dev.programadorthi.routing.annotation.Route - -@Route("/screen") -class Screen1 : Screen { - @Composable - override fun Content() {} -} - -@Route("/screen-object") -object Screen2 : Screen { - @Composable - override fun Content() {} -} - -@Route("/screen/{id}") -class Screen3(id: Int) : Screen { - @Composable - override fun Content() {} -} - -@Route("/screen/{name}") -class Screen4(name: String) : Screen { - - @Route("/screen/{age}") - constructor(age: Int) : this("empty") - - @Composable - override fun Content() {} -} - -@Route("/screen-with-body") -class Screen5(@Body user: User) : Screen { - - @Composable - override fun Content() {} -} diff --git a/settings.gradle.kts b/settings.gradle.kts index c0d6c77..6f1b686 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -46,5 +46,4 @@ include(":integration:voyager") //include(":samples:android-sample") //include(":samples:multiplatform-voyager") //include(":samples:kotlin-js-sample") -//include(":samples:ksp-sample") //include(":samples:win32-sample")