From 7ab2ab42747c18f564dd2a8e30ff34ff2a0b957c Mon Sep 17 00:00:00 2001 From: cmathew Date: Sun, 21 Apr 2024 22:52:31 -0700 Subject: [PATCH 1/7] add composable version of DogListStep --- magellan-sample-migration/build.gradle | 11 +++++ .../sample/migration/tide/DogListStep.kt | 0 .../sample/migration/tide/ComposeStep.kt | 34 +++++++++++++++ .../sample/migration/tide/DogBreedListItem.kt | 23 ++++++++++ .../sample/migration/tide/DogBreeds.kt | 18 ++++++++ .../sample/migration/tide/DogListStep.kt | 43 +++++++++++++++++++ 6 files changed, 129 insertions(+) rename magellan-sample-migration/src/{main/java => androidViews/kotlin}/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt (100%) create mode 100644 magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt create mode 100644 magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt create mode 100644 magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt create mode 100644 magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt diff --git a/magellan-sample-migration/build.gradle b/magellan-sample-migration/build.gradle index ded2af3d..59dae85f 100644 --- a/magellan-sample-migration/build.gradle +++ b/magellan-sample-migration/build.gradle @@ -19,6 +19,17 @@ android { setTargetCompatibility(JavaVersion.VERSION_17) } + flavorDimensions += "ui" + productFlavors { + register("androidViews") { + isDefault = true + dimension = "ui" + } + register("compose") { + dimension = "ui" + } + } + buildFeatures { viewBinding = true } diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt b/magellan-sample-migration/src/androidViews/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt similarity index 100% rename from magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt rename to magellan-sample-migration/src/androidViews/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt diff --git a/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt b/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt new file mode 100644 index 00000000..02d6a416 --- /dev/null +++ b/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt @@ -0,0 +1,34 @@ +package com.wealthfront.magellan.sample.migration.tide + +import androidx.annotation.VisibleForTesting +import androidx.compose.foundation.layout.Box +import androidx.compose.runtime.Composable +import androidx.compose.runtime.saveable.SaveableStateHolder +import androidx.compose.runtime.saveable.rememberSaveableStateHolder +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ComposeView +import com.wealthfront.magellan.core.Navigable +import com.wealthfront.magellan.lifecycle.LifecycleAwareComponent +import com.wealthfront.magellan.lifecycle.createAndAttachFieldToLifecycleWhenShown +import java.util.UUID + +abstract class ComposeStep : Navigable, LifecycleAwareComponent() { + + private var state: SaveableStateHolder? = null + + final override var view: ComposeView? by createAndAttachFieldToLifecycleWhenShown { ComposeView(it) } + @VisibleForTesting set + + fun setContent(content: @Composable () -> Unit) { + view?.setContent { + if (state == null) { + state = rememberSaveableStateHolder() + } + Box(modifier = Modifier) { + state!!.SaveableStateProvider(UUID.randomUUID()) { + content() + } + } + } + } +} \ No newline at end of file diff --git a/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt b/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt new file mode 100644 index 00000000..90b440c8 --- /dev/null +++ b/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt @@ -0,0 +1,23 @@ +package com.wealthfront.magellan.sample.migration.tide + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.material3.Typography +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun DogBreedListItem(breedName: String) { + Text( + text = breedName, + style = Typography().bodyMedium, + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = 16.dp, + vertical = 8.dp + ) + ) +} diff --git a/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt b/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt new file mode 100644 index 00000000..1a212544 --- /dev/null +++ b/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt @@ -0,0 +1,18 @@ +package com.wealthfront.magellan.sample.migration.tide + +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material3.HorizontalDivider +import androidx.compose.runtime.Composable + +@Composable +fun DogBreeds(dogBreeds: List) { + LazyColumn { + itemsIndexed(dogBreeds) { index, item -> + DogBreedListItem(item) + if (index != (dogBreeds.size - 1)) { + HorizontalDivider() + } + } + } +} diff --git a/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt b/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt new file mode 100644 index 00000000..5e3cbcc6 --- /dev/null +++ b/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt @@ -0,0 +1,43 @@ +package com.wealthfront.magellan.sample.migration.tide + +import android.content.Context +import android.widget.Toast +import android.widget.Toast.LENGTH_SHORT +import androidx.compose.runtime.mutableStateListOf +import com.wealthfront.magellan.coroutines.ShownLifecycleScope +import com.wealthfront.magellan.lifecycle.attachFieldToLifecycle +import com.wealthfront.magellan.sample.migration.AppComponentContainer +import com.wealthfront.magellan.sample.migration.api.DogApi +import kotlinx.coroutines.launch +import javax.inject.Inject + +class DogBreedsStep : ComposeStep() { + + @Inject lateinit var api: DogApi + + private val scope by attachFieldToLifecycle(ShownLifecycleScope()) + private val dogBreedsData = mutableStateListOf() + + override fun onCreate(context: Context) { + (context.applicationContext as AppComponentContainer).injector().inject(this) + } + + override fun onShow(context: Context) { + setContent { + DogBreeds(dogBreeds = dogBreedsData) + } + + scope.launch { + // show loading + val breeds = runCatching { api.getListOfAllBreedsOfRetriever() } + breeds.onSuccess { response -> + dogBreedsData.clear() + dogBreedsData.addAll(response.message) + }.onFailure { + Toast.makeText(context, it.message, LENGTH_SHORT).show() + } + // hide loading + } + } + +} \ No newline at end of file From df568f1bd4a3fea3e74500b6f07627f137a22ac7 Mon Sep 17 00:00:00 2001 From: cmathew Date: Mon, 22 Apr 2024 00:24:44 -0700 Subject: [PATCH 2/7] define AGP and kotlin-gradle-plugin at buildsrc level --- build.gradle | 20 ++++++++++++---- buildSrc/build.gradle | 10 +++++++- gradle/libs.versions.toml | 2 +- magellan-sample-migration/build.gradle | 9 +++++-- .../sample/migration/tide/DogListStep.kt | 1 + .../sample/migration/tide/ComposeStep.kt | 0 .../sample/migration/tide/DogBreedListItem.kt | 0 .../sample/migration/tide/DogBreeds.kt | 0 .../sample/migration/tide/DogListStep.kt | 24 +++++++++++-------- .../magellan/sample/migration/AppComponent.kt | 4 ---- 10 files changed, 47 insertions(+), 23 deletions(-) rename magellan-sample-migration/src/androidViews/{kotlin => java}/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt (97%) rename magellan-sample-migration/src/compose/{kotlin => java}/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt (100%) rename magellan-sample-migration/src/compose/{kotlin => java}/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt (100%) rename magellan-sample-migration/src/compose/{kotlin => java}/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt (100%) rename magellan-sample-migration/src/compose/{kotlin => java}/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt (62%) diff --git a/build.gradle b/build.gradle index bad3a330..55e35db2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,22 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. -plugins { - alias(libs.plugins.kotlin.gradle).apply(false) - alias(libs.plugins.kotlinter.gradle).apply(false) - alias(libs.plugins.kotlin.allopen).apply(false) - alias(libs.plugins.detekt) +buildscript { + repositories { + jcenter() + mavenCentral() + maven {url "https://plugins.gradle.org/m2/"} + google() + } + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22") + classpath("org.jmailen.gradle:kotlinter-gradle:3.9.0") + classpath("org.jetbrains.kotlin:kotlin-allopen:1.8.22") + classpath("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.19.0") + } } +apply plugin: 'io.gitlab.arturbosch.detekt' + allprojects { apply from: "$rootDir/gradle/static-analysis.gradle" apply plugin: "kotlin-allopen" diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 80aa1401..eeb89600 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -1,15 +1,23 @@ +buildscript { + repositories { + gradlePluginPortal() + } +} + plugins { - id 'org.jetbrains.kotlin.jvm' version '1.8.21' + id 'org.jetbrains.kotlin.jvm' version '1.8.22' } repositories { jcenter() mavenCentral() google() + gradlePluginPortal() } dependencies { implementation 'com.android.tools.build:gradle:8.1.2' + implementation 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.22' } compileKotlin { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3e69e4b7..0c3a399a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -66,9 +66,9 @@ coroutinesTest = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-t compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } compose-foundation = { group = "androidx.compose.foundation", name = "foundation" } compose-ui = { group = "androidx.compose.ui", name = "ui" } +compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } compose-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } compose-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } -compose-material = { group = "androidx.compose.material", name = "material" } compose-material3 = { group = "androidx.compose.material3", name = "material3" } compose-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } compose-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } diff --git a/magellan-sample-migration/build.gradle b/magellan-sample-migration/build.gradle index 59dae85f..084004e7 100644 --- a/magellan-sample-migration/build.gradle +++ b/magellan-sample-migration/build.gradle @@ -31,9 +31,14 @@ android { } buildFeatures { + compose = true viewBinding = true } + composeOptions { + kotlinCompilerExtensionVersion = "1.4.8" + } + testOptions { unitTests { includeAndroidResources = true @@ -77,12 +82,12 @@ dependencies { implementation libs.jodaTime implementation libs.recyclerView - implementation(enforcedPlatform(libs.compose.bom)) + implementation(platform(libs.compose.bom)) implementation libs.compose.foundation implementation libs.compose.ui + implementation libs.compose.ui.graphics implementation libs.compose.tooling implementation libs.compose.tooling.preview - implementation libs.compose.material implementation libs.compose.material3 kaptTest libs.daggerCompiler diff --git a/magellan-sample-migration/src/androidViews/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt b/magellan-sample-migration/src/androidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt similarity index 97% rename from magellan-sample-migration/src/androidViews/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt rename to magellan-sample-migration/src/androidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt index b0f83810..5a09a20c 100644 --- a/magellan-sample-migration/src/androidViews/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt +++ b/magellan-sample-migration/src/androidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt @@ -6,6 +6,7 @@ import android.widget.Toast import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL +import com.wealthfront.magellan.core.Navigable import com.wealthfront.magellan.core.Step import com.wealthfront.magellan.sample.migration.R import com.wealthfront.magellan.sample.migration.api.DogApi diff --git a/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt similarity index 100% rename from magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt rename to magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt diff --git a/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt similarity index 100% rename from magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt rename to magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt diff --git a/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt similarity index 100% rename from magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt rename to magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt diff --git a/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt similarity index 62% rename from magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt rename to magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt index 5e3cbcc6..e485bbe5 100644 --- a/magellan-sample-migration/src/compose/kotlin/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt +++ b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt @@ -4,24 +4,28 @@ import android.content.Context import android.widget.Toast import android.widget.Toast.LENGTH_SHORT import androidx.compose.runtime.mutableStateListOf +import com.wealthfront.magellan.core.Navigable import com.wealthfront.magellan.coroutines.ShownLifecycleScope import com.wealthfront.magellan.lifecycle.attachFieldToLifecycle -import com.wealthfront.magellan.sample.migration.AppComponentContainer import com.wealthfront.magellan.sample.migration.api.DogApi +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import kotlinx.coroutines.launch -import javax.inject.Inject -class DogBreedsStep : ComposeStep() { +@AssistedFactory +fun interface DogListStepFactory { + fun create(goToDogDetails: (name: String) -> Unit): DogListStep +} - @Inject lateinit var api: DogApi +class DogListStep @AssistedInject constructor( + private val api: DogApi, + @Assisted private val goToDogDetails: (name: String) -> Unit +) : ComposeStep() { private val scope by attachFieldToLifecycle(ShownLifecycleScope()) private val dogBreedsData = mutableStateListOf() - override fun onCreate(context: Context) { - (context.applicationContext as AppComponentContainer).injector().inject(this) - } - override fun onShow(context: Context) { setContent { DogBreeds(dogBreeds = dogBreedsData) @@ -29,10 +33,10 @@ class DogBreedsStep : ComposeStep() { scope.launch { // show loading - val breeds = runCatching { api.getListOfAllBreedsOfRetriever() } + val breeds = runCatching { api.getAllBreeds() } breeds.onSuccess { response -> dogBreedsData.clear() - dogBreedsData.addAll(response.message) + dogBreedsData.addAll(response.message.keys) }.onFailure { Toast.makeText(context, it.message, LENGTH_SHORT).show() } diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.kt index 7add1949..09a91461 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.kt @@ -1,7 +1,5 @@ package com.wealthfront.magellan.sample.migration -import com.wealthfront.magellan.sample.migration.tide.DogDetailsScreen -import com.wealthfront.magellan.sample.migration.tide.DogListStep import dagger.Component import javax.inject.Singleton @@ -10,7 +8,5 @@ import javax.inject.Singleton interface AppComponent { fun inject(activity: MainActivity) - fun inject(step: DogListStep) - fun inject(screen: DogDetailsScreen) fun inject(expedition: Expedition) } From a319ff6ba4d669924fbb7766fd564d43b915ab7c Mon Sep 17 00:00:00 2001 From: cmathew Date: Mon, 22 Apr 2024 09:30:47 -0700 Subject: [PATCH 3/7] organize unit tests by flavor --- .../magellan/sample/migration/uitest/NavigationTest.kt | 1 - .../wealthfront/magellan/sample/migration/tide/DogListStep.kt | 1 - .../wealthfront/magellan/sample/migration/tide/ComposeStep.kt | 2 +- .../wealthfront/magellan/sample/migration/tide/DogListStep.kt | 4 +--- .../wealthfront/magellan/sample/migration/TestAppComponent.kt | 0 .../wealthfront/magellan/sample/migration/TestDogApiModule.kt | 0 .../magellan/sample/migration/TestToolbarHelperModule.kt | 0 .../magellan/sample/migration/tide/DogListStepTest.kt | 0 8 files changed, 2 insertions(+), 6 deletions(-) rename magellan-sample-migration/src/{test => testAndroidViews}/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt (100%) rename magellan-sample-migration/src/{test => testAndroidViews}/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt (100%) rename magellan-sample-migration/src/{test => testAndroidViews}/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt (100%) rename magellan-sample-migration/src/{test => testAndroidViews}/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt (100%) diff --git a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/uitest/NavigationTest.kt b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/uitest/NavigationTest.kt index c1336d37..f0b3aa8e 100644 --- a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/uitest/NavigationTest.kt +++ b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/uitest/NavigationTest.kt @@ -14,7 +14,6 @@ import com.wealthfront.magellan.sample.migration.AppComponentContainer import com.wealthfront.magellan.sample.migration.CoroutineIdlingRule import com.wealthfront.magellan.sample.migration.MainActivity import com.wealthfront.magellan.sample.migration.R -import com.wealthfront.magellan.sample.migration.TestAppComponent import com.wealthfront.magellan.sample.migration.api.DogApi import com.wealthfront.magellan.sample.migration.api.DogBreedsResponse import com.wealthfront.magellan.sample.migration.api.DogImageResponse diff --git a/magellan-sample-migration/src/androidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt b/magellan-sample-migration/src/androidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt index 5a09a20c..b0f83810 100644 --- a/magellan-sample-migration/src/androidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt +++ b/magellan-sample-migration/src/androidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt @@ -6,7 +6,6 @@ import android.widget.Toast import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL -import com.wealthfront.magellan.core.Navigable import com.wealthfront.magellan.core.Step import com.wealthfront.magellan.sample.migration.R import com.wealthfront.magellan.sample.migration.api.DogApi diff --git a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt index 02d6a416..3b1f1cfc 100644 --- a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt +++ b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/ComposeStep.kt @@ -31,4 +31,4 @@ abstract class ComposeStep : Navigable, LifecycleAwareComponent() { } } } -} \ No newline at end of file +} diff --git a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt index e485bbe5..9885a4da 100644 --- a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt +++ b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt @@ -4,7 +4,6 @@ import android.content.Context import android.widget.Toast import android.widget.Toast.LENGTH_SHORT import androidx.compose.runtime.mutableStateListOf -import com.wealthfront.magellan.core.Navigable import com.wealthfront.magellan.coroutines.ShownLifecycleScope import com.wealthfront.magellan.lifecycle.attachFieldToLifecycle import com.wealthfront.magellan.sample.migration.api.DogApi @@ -43,5 +42,4 @@ class DogListStep @AssistedInject constructor( // hide loading } } - -} \ No newline at end of file +} diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt b/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt similarity index 100% rename from magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt rename to magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt b/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt similarity index 100% rename from magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt rename to magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt b/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt similarity index 100% rename from magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt rename to magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt b/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt similarity index 100% rename from magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt rename to magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt From ee4492d18e065e50811c11cf43a4d17f6e3fb9f0 Mon Sep 17 00:00:00 2001 From: cmathew Date: Wed, 24 Apr 2024 11:49:09 -0700 Subject: [PATCH 4/7] attach lazycolumn click listener --- .../sample/migration/tide/DogBreedListItem.kt | 21 ++++++++++++++++--- .../sample/migration/tide/DogBreeds.kt | 4 ++-- .../sample/migration/tide/DogListStep.kt | 2 +- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt index 90b440c8..bb7dd1cc 100644 --- a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt +++ b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreedListItem.kt @@ -1,23 +1,38 @@ package com.wealthfront.magellan.sample.migration.tide +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.Typography import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp @Composable -fun DogBreedListItem(breedName: String) { +fun DogBreedListItem(breedName: String, goToDogDetails: (name: String) -> Unit) { Text( text = breedName, - style = Typography().bodyMedium, + textAlign = TextAlign.Center, + style = Typography().bodyMedium.copy( + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + color = MaterialTheme.colorScheme.primary + ), modifier = Modifier + .clickable { + goToDogDetails(breedName) + } .fillMaxWidth() + .background(MaterialTheme.colorScheme.surface) .padding( horizontal = 16.dp, - vertical = 8.dp + vertical = 16.dp ) ) } diff --git a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt index 1a212544..159916d1 100644 --- a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt +++ b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt @@ -6,10 +6,10 @@ import androidx.compose.material3.HorizontalDivider import androidx.compose.runtime.Composable @Composable -fun DogBreeds(dogBreeds: List) { +fun DogBreeds(dogBreeds: List, onBreedClick: (name: String) -> Unit) { LazyColumn { itemsIndexed(dogBreeds) { index, item -> - DogBreedListItem(item) + DogBreedListItem(item, onBreedClick) if (index != (dogBreeds.size - 1)) { HorizontalDivider() } diff --git a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt index 9885a4da..7ded5c3c 100644 --- a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt +++ b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt @@ -27,7 +27,7 @@ class DogListStep @AssistedInject constructor( override fun onShow(context: Context) { setContent { - DogBreeds(dogBreeds = dogBreedsData) + DogBreeds(dogBreeds = dogBreedsData, onBreedClick = goToDogDetails) } scope.launch { From e62244ed35e17c8fc7ccb550771def067da36bc1 Mon Sep 17 00:00:00 2001 From: cmathew Date: Wed, 24 Apr 2024 11:52:57 -0700 Subject: [PATCH 5/7] clean up build scripts --- buildSrc/build.gradle | 7 ------- gradle/libs.versions.toml | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index eeb89600..973c210d 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -1,9 +1,3 @@ -buildscript { - repositories { - gradlePluginPortal() - } -} - plugins { id 'org.jetbrains.kotlin.jvm' version '1.8.22' } @@ -12,7 +6,6 @@ repositories { jcenter() mavenCentral() google() - gradlePluginPortal() } dependencies { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fa61378f..bc4906ad 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -69,6 +69,7 @@ compose-ui = { group = "androidx.compose.ui", name = "ui" } compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } compose-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } compose-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +compose-material = { group = "androidx.compose.material", name = "material" } compose-material3 = { group = "androidx.compose.material3", name = "material3" } compose-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } compose-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } From 617a48ede03e02dc89ae330239e0b710bd5e2aed Mon Sep 17 00:00:00 2001 From: cmathew Date: Thu, 25 Apr 2024 12:43:00 -0700 Subject: [PATCH 6/7] move class to flavor --- .../wealthfront/magellan/sample/migration/tide/DogListAdapter.kt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename magellan-sample-migration/src/{main => androidViews}/java/com/wealthfront/magellan/sample/migration/tide/DogListAdapter.kt (100%) diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListAdapter.kt b/magellan-sample-migration/src/androidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListAdapter.kt similarity index 100% rename from magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListAdapter.kt rename to magellan-sample-migration/src/androidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListAdapter.kt From 588ce221467fc17650c7f31787c1fb3ebab9e581 Mon Sep 17 00:00:00 2001 From: cmathew Date: Fri, 26 Apr 2024 14:06:11 -0700 Subject: [PATCH 7/7] basic tests for step and composable --- magellan-sample-migration/build.gradle | 3 ++ .../sample/migration/uitest/NavigationTest.kt | 1 + .../res/layout/dashboard.xml | 0 .../res/layout/dog_item.xml | 0 .../sample/migration/tide/DogBreeds.kt | 4 +- .../sample/migration/TestAppComponent.kt | 5 +- .../sample/migration/TestDogApiModule.kt | 0 .../migration/TestToolbarHelperModule.kt | 0 .../sample/migration/tide/DogListStepTest.kt | 5 +- .../resources/robolectric.properties | 2 + .../sample/migration/tide/DogBreedsTest.kt | 30 +++++++++++ .../sample/migration/tide/DogListStepTest.kt | 54 +++++++++++++++++++ 12 files changed, 96 insertions(+), 8 deletions(-) rename magellan-sample-migration/src/{main => androidViews}/res/layout/dashboard.xml (100%) rename magellan-sample-migration/src/{main => androidViews}/res/layout/dog_item.xml (100%) rename magellan-sample-migration/src/{testAndroidViews => test}/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt (90%) rename magellan-sample-migration/src/{testAndroidViews => test}/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt (100%) rename magellan-sample-migration/src/{testAndroidViews => test}/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt (100%) create mode 100644 magellan-sample-migration/src/testAndroidViews/resources/robolectric.properties create mode 100644 magellan-sample-migration/src/testCompose/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsTest.kt create mode 100644 magellan-sample-migration/src/testCompose/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt diff --git a/magellan-sample-migration/build.gradle b/magellan-sample-migration/build.gradle index 084004e7..998e2323 100644 --- a/magellan-sample-migration/build.gradle +++ b/magellan-sample-migration/build.gradle @@ -97,6 +97,9 @@ dependencies { testImplementation libs.mockK testImplementation libs.robolectric testImplementation libs.truth +// testImplementation libs.espressoCore + testImplementation libs.compose.junit4 + testImplementation libs.compose.manifest kaptAndroidTest libs.daggerCompiler androidTestImplementation libs.extJunit diff --git a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/uitest/NavigationTest.kt b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/uitest/NavigationTest.kt index f0b3aa8e..c1336d37 100644 --- a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/uitest/NavigationTest.kt +++ b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/uitest/NavigationTest.kt @@ -14,6 +14,7 @@ import com.wealthfront.magellan.sample.migration.AppComponentContainer import com.wealthfront.magellan.sample.migration.CoroutineIdlingRule import com.wealthfront.magellan.sample.migration.MainActivity import com.wealthfront.magellan.sample.migration.R +import com.wealthfront.magellan.sample.migration.TestAppComponent import com.wealthfront.magellan.sample.migration.api.DogApi import com.wealthfront.magellan.sample.migration.api.DogBreedsResponse import com.wealthfront.magellan.sample.migration.api.DogImageResponse diff --git a/magellan-sample-migration/src/main/res/layout/dashboard.xml b/magellan-sample-migration/src/androidViews/res/layout/dashboard.xml similarity index 100% rename from magellan-sample-migration/src/main/res/layout/dashboard.xml rename to magellan-sample-migration/src/androidViews/res/layout/dashboard.xml diff --git a/magellan-sample-migration/src/main/res/layout/dog_item.xml b/magellan-sample-migration/src/androidViews/res/layout/dog_item.xml similarity index 100% rename from magellan-sample-migration/src/main/res/layout/dog_item.xml rename to magellan-sample-migration/src/androidViews/res/layout/dog_item.xml diff --git a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt index 159916d1..6f323a55 100644 --- a/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt +++ b/magellan-sample-migration/src/compose/java/com/wealthfront/magellan/sample/migration/tide/DogBreeds.kt @@ -4,10 +4,12 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.HorizontalDivider import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag @Composable fun DogBreeds(dogBreeds: List, onBreedClick: (name: String) -> Unit) { - LazyColumn { + LazyColumn(modifier = Modifier.testTag("DogBreeds")) { itemsIndexed(dogBreeds) { index, item -> DogBreedListItem(item, onBreedClick) if (index != (dogBreeds.size - 1)) { diff --git a/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt similarity index 90% rename from magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt rename to magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt index a77c89db..1be7841b 100644 --- a/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt +++ b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt @@ -1,7 +1,7 @@ package com.wealthfront.magellan.sample.migration import com.wealthfront.magellan.sample.migration.api.DogApi -import com.wealthfront.magellan.sample.migration.tide.DogListStepTest +import com.wealthfront.magellan.sample.migration.tide.DogListStepFactory import com.wealthfront.magellan.sample.migration.toolbar.ToolbarHelper import dagger.Component import javax.inject.Singleton @@ -12,6 +12,5 @@ interface TestAppComponent : AppComponent { val toolbarHelper: ToolbarHelper val api: DogApi - - fun inject(test: DogListStepTest) + val dogListStepFactory: DogListStepFactory } diff --git a/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt similarity index 100% rename from magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt rename to magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt diff --git a/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt similarity index 100% rename from magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt rename to magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt diff --git a/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt b/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt index ed89a95e..d903aa9a 100644 --- a/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt +++ b/magellan-sample-migration/src/testAndroidViews/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt @@ -16,13 +16,11 @@ import org.junit.runner.RunWith import org.robolectric.Robolectric import org.robolectric.RobolectricTestRunner import org.robolectric.Shadows.shadowOf -import javax.inject.Inject @RunWith(RobolectricTestRunner::class) class DogListStepTest { private lateinit var dogListStep: DogListStep - @Inject lateinit var dogListStepFactory: DogListStepFactory private val activityController = Robolectric.buildActivity(ComponentActivity::class.java) private var chosenBreed: String? = null @@ -31,8 +29,7 @@ class DogListStepTest { fun setUp() { val context = ApplicationProvider.getApplicationContext() val component = ((context as AppComponentContainer).injector() as TestAppComponent) - component.inject(this) - dogListStep = dogListStepFactory.create { chosenBreed = it } + dogListStep = component.dogListStepFactory.create { chosenBreed = it } coEvery { component.api.getAllBreeds() } returns DogBreedsResponse(message = mapOf("akita" to emptyList()), status = "success") } diff --git a/magellan-sample-migration/src/testAndroidViews/resources/robolectric.properties b/magellan-sample-migration/src/testAndroidViews/resources/robolectric.properties new file mode 100644 index 00000000..c053aedb --- /dev/null +++ b/magellan-sample-migration/src/testAndroidViews/resources/robolectric.properties @@ -0,0 +1,2 @@ +sdk=28 +application=com.wealthfront.magellan.sample.migration.TestSampleApplication \ No newline at end of file diff --git a/magellan-sample-migration/src/testCompose/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsTest.kt b/magellan-sample-migration/src/testCompose/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsTest.kt new file mode 100644 index 00000000..4c87070d --- /dev/null +++ b/magellan-sample-migration/src/testCompose/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsTest.kt @@ -0,0 +1,30 @@ +package com.wealthfront.magellan.sample.migration.tide + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onChildAt +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.performClick +import com.google.common.truth.Truth.assertThat +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class DogBreedsTest { + + @get:Rule + val composeTestRule = createComposeRule() + + @Test + fun goesToSelectedDogBreed() { + var clicked = false + composeTestRule.setContent { + DogBreeds(dogBreeds = listOf("akita"), onBreedClick = { clicked = true }) + } + + composeTestRule.onNodeWithTag("DogBreeds").onChildAt(0).performClick() + + assertThat(clicked).isTrue() + } +} diff --git a/magellan-sample-migration/src/testCompose/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt b/magellan-sample-migration/src/testCompose/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt new file mode 100644 index 00000000..e3cd3d68 --- /dev/null +++ b/magellan-sample-migration/src/testCompose/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt @@ -0,0 +1,54 @@ +package com.wealthfront.magellan.sample.migration.tide + +import android.app.Application +import android.os.Looper.getMainLooper +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onChildAt +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.performClick +import androidx.test.core.app.ApplicationProvider +import com.google.common.truth.Truth.assertThat +import com.wealthfront.magellan.lifecycle.setContentScreen +import com.wealthfront.magellan.sample.migration.AppComponentContainer +import com.wealthfront.magellan.sample.migration.TestAppComponent +import com.wealthfront.magellan.sample.migration.api.DogBreedsResponse +import io.mockk.coEvery +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.Robolectric +import org.robolectric.RobolectricTestRunner +import org.robolectric.Shadows.shadowOf + +@RunWith(RobolectricTestRunner::class) +class DogListStepTest { + + @get:Rule + val composeTestRule = createComposeRule() + + private lateinit var dogListStep: DogListStep + private val activityController = Robolectric.buildActivity(ComponentActivity::class.java) + + private var chosenBreed: String? = null + + @Before + fun setUp() { + val context = ApplicationProvider.getApplicationContext() + val component = ((context as AppComponentContainer).injector() as TestAppComponent) + dogListStep = component.dogListStepFactory.create { chosenBreed = it } + coEvery { component.api.getAllBreeds() } returns + DogBreedsResponse(message = mapOf("akita" to emptyList()), status = "success") + } + + @Test + fun goesToSelectedDogBreed() { + activityController.get().setContentScreen(dogListStep) + activityController.setup() + shadowOf(getMainLooper()).idle() + + composeTestRule.onNodeWithTag("DogBreeds").onChildAt(0).performClick() + assertThat(chosenBreed).isEqualTo("akita") + } +}