From 4e03d7686228387b2996ddcc6dbe67d516f65c9a Mon Sep 17 00:00:00 2001 From: cmathew Date: Wed, 11 Oct 2023 22:47:36 -0700 Subject: [PATCH 1/7] use recyclerview to display dog breeds --- buildSrc/src/main/java/Libs.kt | 2 + buildSrc/src/main/java/Versions.kt | 1 + magellan-sample-migration/build.gradle | 1 + .../sample/migration/tide/DogListStep.kt | 66 ++++++++----------- .../src/main/res/layout/dashboard.xml | 2 +- 5 files changed, 33 insertions(+), 39 deletions(-) diff --git a/buildSrc/src/main/java/Libs.kt b/buildSrc/src/main/java/Libs.kt index ca4ac038..437eaaa0 100644 --- a/buildSrc/src/main/java/Libs.kt +++ b/buildSrc/src/main/java/Libs.kt @@ -20,6 +20,7 @@ import Versions.materialVersion import Versions.mockKVersion import Versions.mockitoVersion import Versions.okhttpVersion +import Versions.recyclerViewVersion import Versions.retrofitVersion import Versions.robolectricVersion import Versions.rxAndroid2Version @@ -48,6 +49,7 @@ object Libs { const val androidXCore = "androidx.core:core-ktx:$androidXCoreVersion" const val material = "com.google.android.material:material:$materialVersion" + const val recyclerView = "androidx.recyclerview:recyclerview:$recyclerViewVersion" const val junit = "junit:junit:$junitVersion" const val truth = "com.google.truth:truth:$truthVersion" const val mockito = "org.mockito:mockito-core:$mockitoVersion" diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt index 6c6417ff..7292a3db 100644 --- a/buildSrc/src/main/java/Versions.kt +++ b/buildSrc/src/main/java/Versions.kt @@ -27,6 +27,7 @@ object Versions { const val jodaTimeVersion = "2.10.9.1" const val javaInjectVersion = "1" const val materialVersion = "1.4.0" + const val recyclerViewVersion = "1.2.1" const val coroutinesVersion = "1.6.4" const val testCoreVersion = "1.4.0" diff --git a/magellan-sample-migration/build.gradle b/magellan-sample-migration/build.gradle index af48ecde..f9b38bf8 100644 --- a/magellan-sample-migration/build.gradle +++ b/magellan-sample-migration/build.gradle @@ -64,6 +64,7 @@ dependencies { implementation Libs.coroutines implementation Libs.coroutinesAndroid implementation Libs.jodaTime + implementation Libs.recyclerView kaptTest Libs.daggerCompiler testImplementation Libs.junit diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt index 3827515a..93f3b8d0 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt @@ -1,19 +1,23 @@ package com.wealthfront.magellan.sample.migration.tide import android.content.Context +import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ArrayAdapter import android.widget.TextView +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL +import androidx.recyclerview.widget.RecyclerView import com.wealthfront.magellan.core.Step import com.wealthfront.magellan.sample.migration.AppComponentContainer import com.wealthfront.magellan.sample.migration.R import com.wealthfront.magellan.sample.migration.databinding.DashboardBinding import com.wealthfront.magellan.sample.migration.toolbar.ToolbarHelper -import java.util.Locale +import kotlinx.coroutines.launch import javax.inject.Inject -class DogListStep(private val goToDogDetails: (name: String) -> Unit) : Step(DashboardBinding::inflate) { +class DogListStep(private val goToDogDetails: (name: String) -> Unit) : + Step(DashboardBinding::inflate) { @Inject lateinit var toolbarHelper: ToolbarHelper @@ -23,50 +27,36 @@ class DogListStep(private val goToDogDetails: (name: String) -> Unit) : Step Unit) : + RecyclerView.Adapter() { - enum class DogBreed { - AKITA, - BEAGLE, - CHOW, - MIX, - LABRADOR, - SHIBA, - HUSKY, - SHIHTZU; + var dataSet: Array = emptyArray() - fun getName(): String { - return name.replace("_", " ").toLowerCase(Locale.getDefault()).capitalize() + class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val textView: TextView = view.findViewById(R.id.dogName) } - fun getBreedName(): String { - return name.replace("_", " ").toLowerCase(Locale.getDefault()) - } - } + override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { + val view = LayoutInflater.from(viewGroup.context) + .inflate(R.layout.dog_item, viewGroup, false) - private inner class DogListAdapter(context: Context) : ArrayAdapter(context, R.layout.dog_item, R.id.dogName, DogBreed.values()) { + return ViewHolder(view) + } - override fun getView( - position: Int, - convertView: View?, - parent: ViewGroup - ): View { - var view = convertView - if (convertView == null) { - view = View.inflate(context, R.layout.dog_item, null) - } - val dogDetail = getItem(position)!! - val dogDetailTextView = view!!.findViewById(R.id.dogName) - dogDetailTextView.text = dogDetail.getName() - view.setOnClickListener { - onDogSelected(dogDetail.getBreedName()) + override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { + viewHolder.textView.text = dataSet[position] + viewHolder.itemView.setOnClickListener { + onDogSelected(dataSet[position]) } - return view } + + override fun getItemCount() = dataSet.size } } diff --git a/magellan-sample-migration/src/main/res/layout/dashboard.xml b/magellan-sample-migration/src/main/res/layout/dashboard.xml index 43f8bb67..94c935db 100644 --- a/magellan-sample-migration/src/main/res/layout/dashboard.xml +++ b/magellan-sample-migration/src/main/res/layout/dashboard.xml @@ -6,7 +6,7 @@ android:orientation="vertical" > - Date: Wed, 11 Oct 2023 22:31:11 -0700 Subject: [PATCH 2/7] add all api methods to interface --- .../magellan/sample/migration/api/DogApi.kt | 28 +++++++++++++++++-- .../sample/migration/tide/DogBreedsStep.kt | 2 +- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt index a9392658..aab63db3 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt @@ -6,8 +6,14 @@ import retrofit2.http.Path interface DogApi { - @GET("breed/retriever/list") - suspend fun getListOfAllBreedsOfRetriever(): DogBreeds + @GET("breed/{id}/list") + suspend fun getAllSubBreeds(@Path("id") breed: String): DogSubBreeds + + @GET("/breeds/list/all") + suspend fun getAllBreeds(): DogBreeds + + @GET("/breed/{id}}/images") + suspend fun getAllBreeds(@Path("id") breed: String): DogImages @GET("breed/{id}/images/random") suspend fun getRandomImageForBreed(@Path("id") breed: String): DogMessage @@ -21,10 +27,26 @@ data class DogMessage( val status: String ) -data class DogBreeds( +data class DogSubBreeds( @JsonProperty("message") val message: List, @JsonProperty("status") val status: String ) + +data class DogImages( + @JsonProperty("message") + val message: List, + + @JsonProperty("status") + val status: String +) + +data class DogBreeds( + @JsonProperty("message") + val message: Map>, + + @JsonProperty("status") + val status: String +) diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStep.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStep.kt index 378f038a..716d69ac 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStep.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStep.kt @@ -30,7 +30,7 @@ class DogBreedsStep : Step(DogBreedBinding::inflate) { override fun onShow(context: Context, binding: DogBreedBinding) { scope.launch { // show loading - val breeds = runCatching { api.getListOfAllBreedsOfRetriever() } + val breeds = runCatching { api.getAllSubBreeds("retriever") } breeds.onSuccess { binding.dogBreeds.adapter = DogBreedListAdapter(context, it.message) }.onFailure { From 3f6a15714cd73a7454b939f6b4a8795890e2b372 Mon Sep 17 00:00:00 2001 From: cmathew Date: Thu, 12 Oct 2023 10:10:02 -0700 Subject: [PATCH 3/7] cleanup help screens --- .../sample/migration/AppComponent.java | 6 -- .../magellan/sample/migration/api/DogApi.kt | 4 +- .../sample/migration/tide/DogBreedsStep.kt | 61 ----------------- .../sample/migration/tide/DogDetailsScreen.kt | 15 ++--- .../sample/migration/tide/DogDetailsView.kt | 14 ++-- .../sample/migration/tide/DogListStep.kt | 18 ++++- .../sample/migration/tide/HelpJourney.kt | 11 ---- .../sample/migration/tide/HelpScreen.kt | 44 ------------- .../sample/migration/tide/HelpView.kt | 32 --------- .../src/main/res/layout/dashboard.xml | 14 +++- .../src/main/res/layout/dog_breed.xml | 12 +++- .../sample/migration/TestAppComponent.java | 9 +-- .../migration/tide/DogBreedsStepTest.kt | 56 ---------------- ...{HelpViewTest.kt => DogDetailsViewTest.kt} | 11 ++-- .../sample/migration/tide/DogListStepTest.kt | 22 ++++++- .../sample/migration/tide/HelpScreenTest.kt | 66 ------------------- 16 files changed, 81 insertions(+), 314 deletions(-) delete mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStep.kt delete mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpJourney.kt delete mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpScreen.kt delete mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpView.kt delete mode 100644 magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStepTest.kt rename magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/{HelpViewTest.kt => DogDetailsViewTest.kt} (82%) delete mode 100644 magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/HelpScreenTest.kt diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.java b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.java index 829cf992..9b6dbdae 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.java +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.java @@ -1,9 +1,7 @@ package com.wealthfront.magellan.sample.migration; -import com.wealthfront.magellan.sample.migration.tide.DogBreedsStep; import com.wealthfront.magellan.sample.migration.tide.DogDetailsScreen; import com.wealthfront.magellan.sample.migration.tide.DogListStep; -import com.wealthfront.magellan.sample.migration.tide.HelpScreen; import javax.inject.Singleton; @@ -19,9 +17,5 @@ public interface AppComponent { void inject(DogDetailsScreen screen); - void inject(DogBreedsStep step); - - void inject(HelpScreen screen); - void inject(Expedition expedition); } diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt index aab63db3..589931f8 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt @@ -9,10 +9,10 @@ interface DogApi { @GET("breed/{id}/list") suspend fun getAllSubBreeds(@Path("id") breed: String): DogSubBreeds - @GET("/breeds/list/all") + @GET("breeds/list/all") suspend fun getAllBreeds(): DogBreeds - @GET("/breed/{id}}/images") + @GET("breed/{id}}/images") suspend fun getAllBreeds(@Path("id") breed: String): DogImages @GET("breed/{id}/images/random") diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStep.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStep.kt deleted file mode 100644 index 716d69ac..00000000 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStep.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.wealthfront.magellan.sample.migration.tide - -import android.content.Context -import android.view.View -import android.view.ViewGroup -import android.widget.ArrayAdapter -import android.widget.TextView -import android.widget.Toast -import android.widget.Toast.LENGTH_SHORT -import com.wealthfront.magellan.core.Step -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.R -import com.wealthfront.magellan.sample.migration.api.DogApi -import com.wealthfront.magellan.sample.migration.databinding.DogBreedBinding -import kotlinx.coroutines.launch -import javax.inject.Inject - -class DogBreedsStep : Step(DogBreedBinding::inflate) { - - @Inject lateinit var api: DogApi - - private val scope by attachFieldToLifecycle(ShownLifecycleScope()) - - override fun onCreate(context: Context) { - (context.applicationContext as AppComponentContainer).injector().inject(this) - } - - override fun onShow(context: Context, binding: DogBreedBinding) { - scope.launch { - // show loading - val breeds = runCatching { api.getAllSubBreeds("retriever") } - breeds.onSuccess { - binding.dogBreeds.adapter = DogBreedListAdapter(context, it.message) - }.onFailure { - Toast.makeText(context, it.message, LENGTH_SHORT).show() - } - // hide loading - } - } - - private inner class DogBreedListAdapter(context: Context, breeds: List) : - ArrayAdapter(context, R.layout.dog_item, R.id.dogName, breeds) { - - override fun getView( - position: Int, - convertView: View?, - parent: ViewGroup - ): View { - var view = convertView - if (convertView == null) { - view = View.inflate(context, R.layout.dog_item, null) - } - val dogDetail = getItem(position)!! - val dogDetailTextView = view!!.findViewById(R.id.dogName) - dogDetailTextView.text = dogDetail - return view - } - } -} diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsScreen.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsScreen.kt index 7d15a64f..b708b5e8 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsScreen.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsScreen.kt @@ -1,7 +1,6 @@ package com.wealthfront.magellan.sample.migration.tide import android.content.Context -import android.view.View import android.widget.Toast import com.wealthfront.magellan.OpenForMocking import com.wealthfront.magellan.Screen @@ -9,7 +8,6 @@ import com.wealthfront.magellan.sample.migration.AppComponentContainer import com.wealthfront.magellan.sample.migration.R import com.wealthfront.magellan.sample.migration.api.DogApi import com.wealthfront.magellan.sample.migration.toolbar.ToolbarHelper -import com.wealthfront.magellan.transitions.CircularRevealTransition import kotlinx.coroutines.launch import javax.inject.Inject @@ -32,12 +30,13 @@ class DogDetailsScreen(private val breed: String) : Screen() { toolbarHelper.setMenuColor(R.color.water) shownScope.launch { - val imageResponse = api.getRandomImageForBreed(breed) - view!!.setDogPic(imageResponse.message) + val imageResponse = runCatching { api.getRandomImageForBreed(breed) } + imageResponse.onSuccess { image -> + view!!.setDogPic(image.message) + } + imageResponse.onFailure { throwable -> + Toast.makeText(context, throwable.message, Toast.LENGTH_SHORT).show() + } } } - - fun goToHelpScreen(originView: View) { - navigator.goTo(HelpJourney(), CircularRevealTransition(originView)) - } } diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsView.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsView.kt index e268fe91..4901243c 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsView.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsView.kt @@ -2,6 +2,7 @@ package com.wealthfront.magellan.sample.migration.tide import android.content.Context import android.view.LayoutInflater +import androidx.annotation.VisibleForTesting import com.bumptech.glide.Glide import com.wealthfront.magellan.BaseScreenView import com.wealthfront.magellan.OpenForMocking @@ -10,17 +11,14 @@ import com.wealthfront.magellan.sample.migration.databinding.DogDetailsBinding @OpenForMocking class DogDetailsView(context: Context) : BaseScreenView(context) { - private val viewBinding = DogDetailsBinding.inflate(LayoutInflater.from(context), this, true) + @VisibleForTesting + var glideBuilder = Glide.with(this) - init { - viewBinding.dogImage.setOnLongClickListener { image -> - screen.goToHelpScreen(image) - return@setOnLongClickListener true - } - } + @VisibleForTesting + val viewBinding = DogDetailsBinding.inflate(LayoutInflater.from(context), this, true) fun setDogPic(dogUrl: String) { - Glide.with(this) + glideBuilder .load(dogUrl) .into(viewBinding.dogImage) } diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt index 93f3b8d0..8e75cb59 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt @@ -5,12 +5,15 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView +import android.widget.Toast +import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL import androidx.recyclerview.widget.RecyclerView import com.wealthfront.magellan.core.Step import com.wealthfront.magellan.sample.migration.AppComponentContainer import com.wealthfront.magellan.sample.migration.R +import com.wealthfront.magellan.sample.migration.api.DogApi import com.wealthfront.magellan.sample.migration.databinding.DashboardBinding import com.wealthfront.magellan.sample.migration.toolbar.ToolbarHelper import kotlinx.coroutines.launch @@ -20,6 +23,7 @@ class DogListStep(private val goToDogDetails: (name: String) -> Unit) : Step(DashboardBinding::inflate) { @Inject lateinit var toolbarHelper: ToolbarHelper + @Inject lateinit var api: DogApi override fun onCreate(context: Context) { (context.applicationContext as AppComponentContainer).injector().inject(this) @@ -29,8 +33,20 @@ class DogListStep(private val goToDogDetails: (name: String) -> Unit) : toolbarHelper.setTitle(context.getText(R.string.app_name)) binding.dogItems.layoutManager = LinearLayoutManager(context, VERTICAL, false) binding.dogItems.adapter = DogListAdapter(goToDogDetails) + val decoration = DividerItemDecoration(context, VERTICAL) + binding.dogItems.addItemDecoration(decoration) + + binding.dogItemsLoading.visibility = View.VISIBLE shownScope.launch { - api + val dogBreedsResponse = runCatching { api.getAllBreeds() } + dogBreedsResponse.onSuccess { dogBreeds -> + (binding.dogItems.adapter as DogListAdapter).dataSet = dogBreeds.message.keys.toTypedArray() + (binding.dogItems.adapter as DogListAdapter).notifyDataSetChanged() + } + dogBreedsResponse.onFailure { throwable -> + Toast.makeText(context, throwable.message, Toast.LENGTH_SHORT).show() + } + binding.dogItemsLoading.visibility = View.GONE } } diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpJourney.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpJourney.kt deleted file mode 100644 index 6152b499..00000000 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpJourney.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.wealthfront.magellan.sample.migration.tide - -import android.content.Context -import com.wealthfront.magellan.core.SimpleJourney - -class HelpJourney : SimpleJourney() { - - override fun onCreate(context: Context) { - navigator.goTo(HelpScreen { navigator.goTo(DogBreedsStep()) }) - } -} diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpScreen.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpScreen.kt deleted file mode 100644 index 53f3653b..00000000 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpScreen.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.wealthfront.magellan.sample.migration.tide - -import android.app.AlertDialog -import android.content.Context -import android.content.DialogInterface -import com.wealthfront.magellan.LegacyStep -import com.wealthfront.magellan.OpenForMocking -import com.wealthfront.magellan.sample.migration.AppComponentContainer -import com.wealthfront.magellan.sample.migration.api.DogApi -import kotlinx.coroutines.launch -import javax.inject.Inject - -@OpenForMocking -class HelpScreen(private val goToBreedsStep: () -> Unit) : LegacyStep() { - - @Inject lateinit var api: DogApi - - override fun onCreate(context: Context) { - (context.applicationContext as AppComponentContainer).injector().inject(this) - } - - override fun createView(context: Context): HelpView { - return HelpView(context, this) - } - - override fun onShow(context: Context) { - shownScope.launch { - val imageResponse = api.getRandomImageForBreed("husky") - view!!.setDogPic(imageResponse.message) - } - } - - fun showHelpDialog() { - dialogComponent.showDialog { context -> - AlertDialog.Builder(context) - .setTitle("Hello") - .setMessage("Did you find the dog you were looking for?") - .setPositiveButton("Find all breeds of retriever") { _: DialogInterface, _: Int -> - goToBreedsStep() - } - .create() - } - } -} diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpView.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpView.kt deleted file mode 100644 index 383d7b9c..00000000 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/HelpView.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.wealthfront.magellan.sample.migration.tide - -import android.annotation.SuppressLint -import android.content.Context -import android.view.LayoutInflater -import android.widget.FrameLayout -import androidx.annotation.VisibleForTesting -import com.bumptech.glide.Glide -import com.wealthfront.magellan.OpenForMocking -import com.wealthfront.magellan.sample.migration.databinding.HelpBinding - -@SuppressLint("ViewConstructor") -@OpenForMocking -class HelpView(context: Context, private val screen: HelpScreen) : FrameLayout(context) { - - @VisibleForTesting - val binding = HelpBinding.inflate(LayoutInflater.from(context), this, true) - @VisibleForTesting - var glideBuilder = Glide.with(this) - - init { - binding.dialog.setOnClickListener { - screen.showHelpDialog() - } - } - - fun setDogPic(dogUrl: String) { - glideBuilder - .load(dogUrl) - .into(binding.dogImage) - } -} diff --git a/magellan-sample-migration/src/main/res/layout/dashboard.xml b/magellan-sample-migration/src/main/res/layout/dashboard.xml index 94c935db..c267719c 100644 --- a/magellan-sample-migration/src/main/res/layout/dashboard.xml +++ b/magellan-sample-migration/src/main/res/layout/dashboard.xml @@ -1,11 +1,19 @@ - + + - \ No newline at end of file + \ No newline at end of file diff --git a/magellan-sample-migration/src/main/res/layout/dog_breed.xml b/magellan-sample-migration/src/main/res/layout/dog_breed.xml index 6fc82e59..c41fee16 100644 --- a/magellan-sample-migration/src/main/res/layout/dog_breed.xml +++ b/magellan-sample-migration/src/main/res/layout/dog_breed.xml @@ -1,12 +1,18 @@ - + + - \ No newline at end of file + \ No newline at end of file diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.java b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.java index 0e6ab5d0..ec13ef46 100644 --- a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.java +++ b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.java @@ -1,8 +1,7 @@ package com.wealthfront.magellan.sample.migration; -import com.wealthfront.magellan.sample.migration.tide.DogBreedsStepTest; import com.wealthfront.magellan.sample.migration.tide.DogDetailsScreenTest; -import com.wealthfront.magellan.sample.migration.tide.HelpScreenTest; +import com.wealthfront.magellan.sample.migration.tide.DogListStepTest; import javax.inject.Singleton; @@ -11,9 +10,7 @@ @Component(modules = TestAppModule.class) @Singleton public interface TestAppComponent extends AppComponent { - void inject(HelpScreenTest test); - - void inject(DogBreedsStepTest test); - void inject(DogDetailsScreenTest test); + + void inject(DogListStepTest test); } diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStepTest.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStepTest.kt deleted file mode 100644 index 0257b64d..00000000 --- a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogBreedsStepTest.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.wealthfront.magellan.sample.migration.tide - -import android.app.Activity -import android.app.Application -import android.os.Looper -import androidx.test.core.app.ApplicationProvider.getApplicationContext -import com.google.common.truth.Truth.assertThat -import com.wealthfront.magellan.lifecycle.LifecycleState -import com.wealthfront.magellan.lifecycle.transitionToState -import com.wealthfront.magellan.sample.migration.AppComponentContainer -import com.wealthfront.magellan.sample.migration.TestAppComponent -import com.wealthfront.magellan.sample.migration.api.DogApi -import com.wealthfront.magellan.sample.migration.api.DogBreeds -import com.wealthfront.magellan.sample.migration.coWhen -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.junit.MockitoJUnit -import org.mockito.junit.MockitoRule -import org.mockito.quality.Strictness -import org.robolectric.Robolectric -import org.robolectric.RobolectricTestRunner -import org.robolectric.Shadows.shadowOf -import javax.inject.Inject - -@RunWith(RobolectricTestRunner::class) -class DogBreedsStepTest { - - private val dogBreedsStep = DogBreedsStep() - private val activity = Robolectric.buildActivity(Activity::class.java).get() - - @Inject lateinit var api: DogApi - - @Rule @JvmField - val mockitoRule: MockitoRule = MockitoJUnit.rule().strictness(Strictness.WARN) - - @Before - fun setup() { - val context = getApplicationContext() - ((context as AppComponentContainer).injector() as TestAppComponent).inject(this) - - val breedData = DogBreeds( - message = listOf("chesapeake", "curly", "flatcoated", "golden"), - status = "success" - ) - coWhen { api.getListOfAllBreedsOfRetriever() }.thenReturn(breedData) - } - - @Test - fun fetchesDogBreedsOnShow() { - dogBreedsStep.transitionToState(LifecycleState.Shown(activity)) - shadowOf(Looper.getMainLooper()).idle() - assertThat(dogBreedsStep.viewBinding!!.dogBreeds.adapter).isNotNull() - } -} diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/HelpViewTest.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsViewTest.kt similarity index 82% rename from magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/HelpViewTest.kt rename to magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsViewTest.kt index 8d44c10d..f76f86c2 100644 --- a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/HelpViewTest.kt +++ b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsViewTest.kt @@ -21,13 +21,12 @@ import org.robolectric.RobolectricTestRunner import org.robolectric.Shadows.shadowOf @RunWith(RobolectricTestRunner::class) -class HelpViewTest { +class DogDetailsViewTest { - @Mock lateinit var screen: HelpScreen @Mock lateinit var glideRequest: RequestManager @Mock lateinit var drawableRequest: RequestBuilder - private lateinit var helpView: HelpView + private lateinit var view: DogDetailsView private lateinit var context: Context @Rule @JvmField @@ -36,7 +35,7 @@ class HelpViewTest { @Before fun setup() { context = ApplicationProvider.getApplicationContext() - helpView = HelpView(context, screen).apply { + view = DogDetailsView(context).apply { glideBuilder = glideRequest } @@ -45,8 +44,8 @@ class HelpViewTest { @Test fun fetchesDogPicOnShow() { - helpView.setDogPic("https://dailybeagle.com/latest-picture") + view.setDogPic("https://dailybeagle.com/latest-picture") shadowOf(getMainLooper()).idle() - verify(drawableRequest).into(helpView.binding.dogImage) + verify(drawableRequest).into(view.viewBinding.dogImage) } } diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt index a6f2d416..f664e042 100644 --- a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt +++ b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt @@ -1,28 +1,48 @@ package com.wealthfront.magellan.sample.migration.tide +import android.app.Application import android.os.Looper.getMainLooper import androidx.activity.ComponentActivity +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.DogApi +import com.wealthfront.magellan.sample.migration.api.DogBreeds +import com.wealthfront.magellan.sample.migration.coWhen +import org.junit.Before import org.junit.Test 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 { + @Inject lateinit var api: DogApi + private var chosenBreed: String? = null private val dogListStep = DogListStep { chosenBreed = it } private val activityController = Robolectric.buildActivity(ComponentActivity::class.java) + @Before + fun setUp() { + val context = ApplicationProvider.getApplicationContext() + ((context as AppComponentContainer).injector() as TestAppComponent).inject(this) + + coWhen { api.getAllBreeds() } + .thenReturn(DogBreeds(message = mapOf("akita" to emptyList()), status = "success")) + } + @Test fun goesToSelectedDogBreed() { activityController.get().setContentScreen(dogListStep) activityController.setup() shadowOf(getMainLooper()).idle() - dogListStep.viewBinding!!.dogItems.getChildAt(0).performClick() + dogListStep.viewBinding!!.dogItems.findViewHolderForAdapterPosition(0)!!.itemView.performClick() assertThat(chosenBreed).isEqualTo("akita") } } diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/HelpScreenTest.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/HelpScreenTest.kt deleted file mode 100644 index 661a28c6..00000000 --- a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/HelpScreenTest.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.wealthfront.magellan.sample.migration.tide - -import android.content.Context -import android.os.Looper.getMainLooper -import androidx.test.core.app.ApplicationProvider -import com.wealthfront.magellan.lifecycle.LifecycleState -import com.wealthfront.magellan.lifecycle.transitionToState -import com.wealthfront.magellan.sample.migration.AppComponentContainer -import com.wealthfront.magellan.sample.migration.TestAppComponent -import com.wealthfront.magellan.sample.migration.api.DogApi -import com.wealthfront.magellan.sample.migration.api.DogMessage -import com.wealthfront.magellan.sample.migration.coWhen -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mock -import org.mockito.Mockito.verify -import org.mockito.junit.MockitoJUnit -import org.mockito.junit.MockitoRule -import org.mockito.quality.Strictness -import org.robolectric.RobolectricTestRunner -import org.robolectric.Shadows.shadowOf -import javax.inject.Inject - -@RunWith(RobolectricTestRunner::class) -class HelpScreenTest { - - @Mock lateinit var helpView: HelpView - - private lateinit var helpScreen: HelpScreen - private lateinit var context: Context - private var goToBreedsStep = false - - @Inject lateinit var api: DogApi - - @Rule @JvmField - val mockitoRule: MockitoRule = MockitoJUnit.rule().strictness(Strictness.WARN) - - @Before - fun setup() { - context = ApplicationProvider.getApplicationContext() - ((context as AppComponentContainer).injector() as TestAppComponent).inject(this) - - helpScreen = object : HelpScreen({ goToBreedsStep = true }) { - override fun createView(context: Context): HelpView { - super.createView(context) - return helpView - } - } - - coWhen { api.getRandomImageForBreed("husky") }.thenReturn( - DogMessage( - message = "https://dailybeagle.com/latest-picture", - status = "something" - ) - ) - } - - @Test - fun fetchesDogPicOnShow() { - helpScreen.transitionToState(LifecycleState.Shown(context)) - shadowOf(getMainLooper()).idle() - verify(helpView).setDogPic("https://dailybeagle.com/latest-picture") - } -} From d2ffab34b3f527f2a9c52d11312eea7d033ec6c4 Mon Sep 17 00:00:00 2001 From: cmathew Date: Thu, 12 Oct 2023 11:33:48 -0700 Subject: [PATCH 4/7] mock dog API in integration tests --- buildSrc/src/main/java/Libs.kt | 1 + magellan-sample-migration/build.gradle | 4 +- .../migration}/CoroutineIdlingRule.kt | 2 +- .../sample/migration/IntegrationTestRunner.kt | 21 ++++++ .../sample/migration/TestAppComponent.kt | 12 ++++ .../sample/migration/TestDogApiModule.kt | 17 +++++ .../sample/migration/TestExtensions.kt | 33 +++++++++ .../sample/migration/TestSampleApplication.kt | 21 ++++++ .../sample/migration/uitest/NavigationTest.kt | 54 +++++++++++++++ .../magellan/uitest/NavigationTest.kt | 35 ---------- .../sample/migration/AppComponent.java | 21 ------ .../magellan/sample/migration/AppComponent.kt | 16 +++++ .../magellan/sample/migration/AppModule.java | 67 ------------------- .../magellan/sample/migration/AppModule.kt | 50 ++++++++++++++ .../magellan/sample/migration/DogApiModule.kt | 17 +++++ .../sample/migration/SampleApplication.kt | 8 ++- .../sample/migration/ToolbarHelperModule.kt | 16 +++++ .../sample/migration/TestAppComponent.java | 16 ----- .../sample/migration/TestAppComponent.kt | 14 ++++ .../sample/migration/TestAppModule.java | 40 ----------- .../sample/migration/TestDogApiModule.kt | 17 +++++ .../sample/migration/TestSampleApplication.kt | 4 +- .../migration/TestToolbarHelperModule.kt | 17 +++++ 23 files changed, 318 insertions(+), 185 deletions(-) rename magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/{ => sample/migration}/CoroutineIdlingRule.kt (95%) create mode 100644 magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/IntegrationTestRunner.kt create mode 100644 magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt create mode 100644 magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt create mode 100644 magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestExtensions.kt create mode 100644 magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestSampleApplication.kt create mode 100644 magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/uitest/NavigationTest.kt delete mode 100644 magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/uitest/NavigationTest.kt delete mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.java create mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.kt delete mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppModule.java create mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppModule.kt create mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/DogApiModule.kt create mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/ToolbarHelperModule.kt delete mode 100644 magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.java create mode 100644 magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt delete mode 100644 magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppModule.java create mode 100644 magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt create mode 100644 magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt diff --git a/buildSrc/src/main/java/Libs.kt b/buildSrc/src/main/java/Libs.kt index 437eaaa0..6a87a06a 100644 --- a/buildSrc/src/main/java/Libs.kt +++ b/buildSrc/src/main/java/Libs.kt @@ -53,6 +53,7 @@ object Libs { const val junit = "junit:junit:$junitVersion" const val truth = "com.google.truth:truth:$truthVersion" const val mockito = "org.mockito:mockito-core:$mockitoVersion" + const val mockitoAndroid = "org.mockito:mockito-android:$mockitoVersion" const val mockK = "io.mockk:mockk:$mockKVersion" const val archTesting = "androidx.arch.core:core-testing:$archVersion" const val robolectric = "org.robolectric:robolectric:$robolectricVersion" diff --git a/magellan-sample-migration/build.gradle b/magellan-sample-migration/build.gradle index f9b38bf8..6a09fb95 100644 --- a/magellan-sample-migration/build.gradle +++ b/magellan-sample-migration/build.gradle @@ -11,7 +11,7 @@ android { targetSdkVersion Versions.targetSdkVersion versionCode 1 versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "com.wealthfront.magellan.sample.migration.IntegrationTestRunner" } compileOptions { @@ -74,6 +74,7 @@ dependencies { testImplementation Libs.robolectric testImplementation Libs.truth + kaptAndroidTest Libs.daggerCompiler androidTestImplementation Libs.extJunit androidTestImplementation Libs.espressoCore androidTestImplementation Libs.espressoContrib @@ -81,6 +82,7 @@ dependencies { androidTestImplementation Libs.testCoreKtx androidTestImplementation Libs.testRunner androidTestImplementation Libs.testRules + androidTestImplementation Libs.mockitoAndroid androidTestImplementation 'androidx.test:runner:1.4.0' androidTestUtil 'androidx.test:orchestrator:1.4.1' diff --git a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/CoroutineIdlingRule.kt b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/CoroutineIdlingRule.kt similarity index 95% rename from magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/CoroutineIdlingRule.kt rename to magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/CoroutineIdlingRule.kt index 2e99f74d..df0d08c3 100644 --- a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/CoroutineIdlingRule.kt +++ b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/CoroutineIdlingRule.kt @@ -1,4 +1,4 @@ -package com.wealthfront.magellan +package com.wealthfront.magellan.sample.migration import androidx.test.espresso.IdlingRegistry import androidx.test.espresso.idling.CountingIdlingResource diff --git a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/IntegrationTestRunner.kt b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/IntegrationTestRunner.kt new file mode 100644 index 00000000..ec93d466 --- /dev/null +++ b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/IntegrationTestRunner.kt @@ -0,0 +1,21 @@ +package com.wealthfront.magellan.sample.migration + +import android.app.Application +import android.content.Context +import androidx.test.runner.AndroidJUnitRunner + +class IntegrationTestRunner : AndroidJUnitRunner() { + + @Throws( + InstantiationException::class, + IllegalAccessException::class, + ClassNotFoundException::class + ) + override fun newApplication( + cl: ClassLoader, + className: String, + context: Context, + ): Application { + return super.newApplication(cl, TestSampleApplication::class.java.name, context) + } +} diff --git a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt new file mode 100644 index 00000000..43113fe9 --- /dev/null +++ b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt @@ -0,0 +1,12 @@ +package com.wealthfront.magellan.sample.migration + +import com.wealthfront.magellan.sample.migration.uitest.NavigationTest +import dagger.Component +import javax.inject.Singleton + +@Component(modules = [AppModule::class, ToolbarHelperModule::class, TestDogApiModule::class]) +@Singleton +interface TestAppComponent : AppComponent { + + fun inject(test: NavigationTest) +} diff --git a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt new file mode 100644 index 00000000..a1db3e03 --- /dev/null +++ b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt @@ -0,0 +1,17 @@ +package com.wealthfront.magellan.sample.migration + +import com.wealthfront.magellan.sample.migration.api.DogApi +import dagger.Module +import dagger.Provides +import org.mockito.Mockito.mock +import javax.inject.Singleton + +@Module +object TestDogApiModule { + + @Provides + @Singleton + fun provideDogApi(): DogApi { + return mock(DogApi::class.java) + } +} diff --git a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestExtensions.kt b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestExtensions.kt new file mode 100644 index 00000000..eea7c3fd --- /dev/null +++ b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestExtensions.kt @@ -0,0 +1,33 @@ +@file:Suppress("UNCHECKED_CAST") + +package com.wealthfront.magellan.sample.migration + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.runBlocking +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` +import org.mockito.stubbing.LenientStubber +import org.mockito.stubbing.OngoingStubbing +import org.mockito.verification.VerificationMode + +fun LenientStubber.coWhen(block: suspend CoroutineScope.() -> T): OngoingStubbing = + runBlocking { + this@coWhen.`when`(block()) + } + +fun coWhen(block: suspend CoroutineScope.() -> T): OngoingStubbing = + runBlocking { + `when`(block()) + } + +fun coVerify(mock: T, block: suspend CoroutineScope.(T) -> Unit) { + runBlocking { + block(verify(mock)) + } +} + +fun coVerify(mock: T, mode: VerificationMode, block: suspend CoroutineScope.(T) -> Unit) { + runBlocking { + block(verify(mock, mode)) + } +} diff --git a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestSampleApplication.kt b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestSampleApplication.kt new file mode 100644 index 00000000..b7cb41c8 --- /dev/null +++ b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/TestSampleApplication.kt @@ -0,0 +1,21 @@ +package com.wealthfront.magellan.sample.migration + +import android.app.Application + +class TestSampleApplication : Application(), AppComponentContainer { + + private lateinit var appComponent: TestAppComponent + + override fun onCreate() { + super.onCreate() + appComponent = DaggerTestAppComponent.builder() + .appModule(AppModule) + .testDogApiModule(TestDogApiModule) + .toolbarHelperModule(ToolbarHelperModule) + .build() + } + + override fun injector(): AppComponent { + return appComponent + } +} 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 new file mode 100644 index 00000000..a75002e4 --- /dev/null +++ b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/sample/migration/uitest/NavigationTest.kt @@ -0,0 +1,54 @@ +package com.wealthfront.magellan.sample.migration.uitest + +import android.app.Application +import androidx.test.core.app.ActivityScenario +import androidx.test.core.app.ApplicationProvider +import androidx.test.core.app.launchActivity +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +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.DogBreeds +import com.wealthfront.magellan.sample.migration.api.DogMessage +import com.wealthfront.magellan.sample.migration.coWhen +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import javax.inject.Inject + +class NavigationTest { + + @Rule @JvmField + val coroutineIdlingRule = CoroutineIdlingRule() + + @Inject lateinit var api: DogApi + + private lateinit var activityScenario: ActivityScenario + + @Before + fun setup() { + val context = ApplicationProvider.getApplicationContext() + ((context as AppComponentContainer).injector() as TestAppComponent).inject(this) + + coWhen { api.getAllBreeds() } + .thenReturn(DogBreeds(message = mapOf("robotic" to emptyList()), status = "success")) + coWhen { api.getRandomImageForBreed("robotic") }.thenReturn( + DogMessage(message = "image-url", status = "success") + ) + } + + @Test + fun visitRetriever() { + activityScenario = launchActivity() + onView(withText("robotic")).perform(click()) + onView(withId(R.id.dogDetailsView)).check(matches(isDisplayed())) + } +} diff --git a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/uitest/NavigationTest.kt b/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/uitest/NavigationTest.kt deleted file mode 100644 index 83b65cca..00000000 --- a/magellan-sample-migration/src/androidTest/java/com/wealthfront/magellan/uitest/NavigationTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.wealthfront.magellan.uitest - -import androidx.test.core.app.ActivityScenario -import androidx.test.core.app.launchActivity -import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.action.ViewActions.click -import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.matcher.ViewMatchers.isDisplayed -import androidx.test.espresso.matcher.ViewMatchers.withId -import androidx.test.espresso.matcher.ViewMatchers.withText -import com.wealthfront.magellan.CoroutineIdlingRule -import com.wealthfront.magellan.sample.migration.MainActivity -import com.wealthfront.magellan.sample.migration.R -import org.junit.Before -import org.junit.Rule -import org.junit.Test - -class NavigationTest { - - @Rule @JvmField - val coroutineIdlingRule = CoroutineIdlingRule() - - private lateinit var activityScenario: ActivityScenario - - @Before - fun setup() { - activityScenario = launchActivity() - } - - @Test - fun visitRetriever() { - onView(withText("Akita")).perform(click()) - onView(withId(R.id.dogDetailsView)).check(matches(isDisplayed())) - } -} diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.java b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.java deleted file mode 100644 index 9b6dbdae..00000000 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.wealthfront.magellan.sample.migration; - -import com.wealthfront.magellan.sample.migration.tide.DogDetailsScreen; -import com.wealthfront.magellan.sample.migration.tide.DogListStep; - -import javax.inject.Singleton; - -import dagger.Component; - -@Component(modules = AppModule.class) -@Singleton -public interface AppComponent { - - void inject(MainActivity activity); - - void inject(DogListStep step); - - void inject(DogDetailsScreen screen); - - void inject(Expedition expedition); -} 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 new file mode 100644 index 00000000..7add1949 --- /dev/null +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppComponent.kt @@ -0,0 +1,16 @@ +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 + +@Component(modules = [AppModule::class, DogApiModule::class, ToolbarHelperModule::class]) +@Singleton +interface AppComponent { + + fun inject(activity: MainActivity) + fun inject(step: DogListStep) + fun inject(screen: DogDetailsScreen) + fun inject(expedition: Expedition) +} diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppModule.java b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppModule.java deleted file mode 100644 index a8064c02..00000000 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppModule.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.wealthfront.magellan.sample.migration; - -import com.wealthfront.magellan.navigation.NavigationTraverser; -import com.wealthfront.magellan.sample.migration.api.DogApi; -import com.wealthfront.magellan.sample.migration.api.RequestCountingInterceptor; -import com.wealthfront.magellan.sample.migration.toolbar.ToolbarHelper; - -import javax.inject.Singleton; - -import dagger.Module; -import dagger.Provides; -import okhttp3.OkHttpClient; -import okhttp3.logging.HttpLoggingInterceptor; -import retrofit2.Retrofit; -import retrofit2.converter.jackson.JacksonConverterFactory; - -@Module -final class AppModule { - - private static final String DOG_BASE_URL = "https://dog.ceo/api/"; - - @Provides - @Singleton - ToolbarHelper provideToolbarHelper() { - return new ToolbarHelper(); - } - - @Provides - @Singleton - Expedition provideExpedition() { - return new Expedition(); - } - - @Provides - @Singleton - NavigationTraverser provideNavigationTraverser(Expedition root) { - return new NavigationTraverser(root); - } - - @Provides - @Singleton - DogApi provideDogApi(Retrofit retrofit) { - return retrofit.create(DogApi.class); - } - - @Provides - @Singleton - Retrofit provideRetrofit(OkHttpClient httpClient) { - return new Retrofit.Builder() - .baseUrl(DOG_BASE_URL) - .addConverterFactory(JacksonConverterFactory.create()) - .client(httpClient) - .build(); - } - - @Provides - @Singleton - OkHttpClient provideHttpClient() { - HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); - interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); - return new OkHttpClient.Builder() - .addInterceptor(interceptor) - .addInterceptor(new RequestCountingInterceptor()) - .build(); - } - -} diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppModule.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppModule.kt new file mode 100644 index 00000000..28dd4fff --- /dev/null +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/AppModule.kt @@ -0,0 +1,50 @@ +package com.wealthfront.magellan.sample.migration + +import com.wealthfront.magellan.navigation.NavigationTraverser +import com.wealthfront.magellan.sample.migration.api.RequestCountingInterceptor +import dagger.Module +import dagger.Provides +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.converter.jackson.JacksonConverterFactory +import javax.inject.Singleton + +private const val DOG_BASE_URL = "https://dog.ceo/api/" + +@Module +object AppModule { + + @Provides + @Singleton + fun provideExpedition(): Expedition { + return Expedition() + } + + @Provides + @Singleton + fun provideNavigationTraverser(root: Expedition): NavigationTraverser { + return NavigationTraverser(root) + } + + @Provides + @Singleton + fun provideRetrofit(httpClient: OkHttpClient): Retrofit { + return Retrofit.Builder() + .baseUrl(DOG_BASE_URL) + .addConverterFactory(JacksonConverterFactory.create()) + .client(httpClient) + .build() + } + + @Provides + @Singleton + fun provideHttpClient(): OkHttpClient { + val interceptor = HttpLoggingInterceptor() + interceptor.setLevel(HttpLoggingInterceptor.Level.BODY) + return OkHttpClient.Builder() + .addInterceptor(interceptor) + .addInterceptor(RequestCountingInterceptor()) + .build() + } +} diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/DogApiModule.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/DogApiModule.kt new file mode 100644 index 00000000..b45a534d --- /dev/null +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/DogApiModule.kt @@ -0,0 +1,17 @@ +package com.wealthfront.magellan.sample.migration + +import com.wealthfront.magellan.sample.migration.api.DogApi +import dagger.Module +import dagger.Provides +import retrofit2.Retrofit +import javax.inject.Singleton + +@Module +object DogApiModule { + + @Provides + @Singleton + fun provideDogApi(retrofit: Retrofit): DogApi { + return retrofit.create(DogApi::class.java) + } +} diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/SampleApplication.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/SampleApplication.kt index 5a7329e9..ea532f00 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/SampleApplication.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/SampleApplication.kt @@ -10,7 +10,9 @@ class SampleApplication : Application(), AppComponentContainer { override fun onCreate() { super.onCreate() appComponent = DaggerAppComponent.builder() - .appModule(AppModule()) + .appModule(AppModule) + .dogApiModule(DogApiModule) + .toolbarHelperModule(ToolbarHelperModule) .build() } @@ -20,8 +22,8 @@ class SampleApplication : Application(), AppComponentContainer { companion object { @JvmStatic - fun app(context: Context): SampleApplication { - return context.applicationContext as SampleApplication + fun app(context: Context): AppComponentContainer { + return context.applicationContext as AppComponentContainer } } } diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/ToolbarHelperModule.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/ToolbarHelperModule.kt new file mode 100644 index 00000000..c47530db --- /dev/null +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/ToolbarHelperModule.kt @@ -0,0 +1,16 @@ +package com.wealthfront.magellan.sample.migration + +import com.wealthfront.magellan.sample.migration.toolbar.ToolbarHelper +import dagger.Module +import dagger.Provides +import javax.inject.Singleton + +@Module +object ToolbarHelperModule { + + @Provides + @Singleton + fun provideToolbarHelper(): ToolbarHelper { + return ToolbarHelper() + } +} diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.java b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.java deleted file mode 100644 index ec13ef46..00000000 --- a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.wealthfront.magellan.sample.migration; - -import com.wealthfront.magellan.sample.migration.tide.DogDetailsScreenTest; -import com.wealthfront.magellan.sample.migration.tide.DogListStepTest; - -import javax.inject.Singleton; - -import dagger.Component; - -@Component(modules = TestAppModule.class) -@Singleton -public interface TestAppComponent extends AppComponent { - void inject(DogDetailsScreenTest test); - - void inject(DogListStepTest test); -} diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt new file mode 100644 index 00000000..16f01467 --- /dev/null +++ b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppComponent.kt @@ -0,0 +1,14 @@ +package com.wealthfront.magellan.sample.migration + +import com.wealthfront.magellan.sample.migration.tide.DogDetailsScreenTest +import com.wealthfront.magellan.sample.migration.tide.DogListStepTest +import dagger.Component +import javax.inject.Singleton + +@Component(modules = [AppModule::class, TestDogApiModule::class, TestToolbarHelperModule::class]) +@Singleton +interface TestAppComponent : AppComponent { + + fun inject(test: DogDetailsScreenTest) + fun inject(test: DogListStepTest) +} diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppModule.java b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppModule.java deleted file mode 100644 index 992dc403..00000000 --- a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestAppModule.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.wealthfront.magellan.sample.migration; - -import com.wealthfront.magellan.navigation.NavigationTraverser; -import com.wealthfront.magellan.sample.migration.api.DogApi; -import com.wealthfront.magellan.sample.migration.toolbar.ToolbarHelper; - -import org.mockito.Mockito; - -import javax.inject.Singleton; - -import dagger.Module; -import dagger.Provides; - -@Module -final class TestAppModule { - - @Provides - @Singleton - Expedition provideExpedition() { - return new Expedition(); - } - - @Provides - @Singleton - NavigationTraverser provideNavigationTraverser(Expedition root) { - return new NavigationTraverser(root); - } - - @Provides - @Singleton - DogApi provideDogApi() { - return Mockito.mock(DogApi.class); - } - - @Provides - @Singleton - ToolbarHelper provideToolbarHelper() { - return Mockito.mock(ToolbarHelper.class); - } -} diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt new file mode 100644 index 00000000..895a3089 --- /dev/null +++ b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestDogApiModule.kt @@ -0,0 +1,17 @@ +package com.wealthfront.magellan.sample.migration + +import com.wealthfront.magellan.sample.migration.api.DogApi +import dagger.Module +import dagger.Provides +import org.mockito.Mockito +import javax.inject.Singleton + +@Module +object TestDogApiModule { + + @Provides + @Singleton + fun provideDogApi(): DogApi { + return Mockito.mock(DogApi::class.java) + } +} diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestSampleApplication.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestSampleApplication.kt index 76811834..b02378a9 100644 --- a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestSampleApplication.kt +++ b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestSampleApplication.kt @@ -9,7 +9,9 @@ class TestSampleApplication : Application(), AppComponentContainer { override fun onCreate() { super.onCreate() appComponent = DaggerTestAppComponent.builder() - .testAppModule(TestAppModule()) + .appModule(AppModule) + .testDogApiModule(TestDogApiModule) + .testToolbarHelperModule(TestToolbarHelperModule) .build() } diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt new file mode 100644 index 00000000..ecdd8461 --- /dev/null +++ b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/TestToolbarHelperModule.kt @@ -0,0 +1,17 @@ +package com.wealthfront.magellan.sample.migration + +import com.wealthfront.magellan.sample.migration.toolbar.ToolbarHelper +import dagger.Module +import dagger.Provides +import org.mockito.Mockito.mock +import javax.inject.Singleton + +@Module +object TestToolbarHelperModule { + + @Provides + @Singleton + fun provideToolbarHelper(): ToolbarHelper { + return mock(ToolbarHelper::class.java) + } +} From 8c38a50b7737586e76bd5d39767856d483f65817 Mon Sep 17 00:00:00 2001 From: cmathew Date: Thu, 12 Oct 2023 11:44:48 -0700 Subject: [PATCH 5/7] rename api classes for clarity --- .../sample/migration/uitest/NavigationTest.kt | 8 ++++---- .../magellan/sample/migration/api/DogApi.kt | 16 ++++++++-------- .../migration/tide/DogDetailsScreenTest.kt | 4 ++-- .../sample/migration/tide/DogListStepTest.kt | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) 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 a75002e4..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 @@ -16,8 +16,8 @@ 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.DogBreeds -import com.wealthfront.magellan.sample.migration.api.DogMessage +import com.wealthfront.magellan.sample.migration.api.DogBreedsResponse +import com.wealthfront.magellan.sample.migration.api.DogImageResponse import com.wealthfront.magellan.sample.migration.coWhen import org.junit.Before import org.junit.Rule @@ -39,9 +39,9 @@ class NavigationTest { ((context as AppComponentContainer).injector() as TestAppComponent).inject(this) coWhen { api.getAllBreeds() } - .thenReturn(DogBreeds(message = mapOf("robotic" to emptyList()), status = "success")) + .thenReturn(DogBreedsResponse(message = mapOf("robotic" to emptyList()), status = "success")) coWhen { api.getRandomImageForBreed("robotic") }.thenReturn( - DogMessage(message = "image-url", status = "success") + DogImageResponse(message = "image-url", status = "success") ) } diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt index 589931f8..9df777f0 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt @@ -7,19 +7,19 @@ import retrofit2.http.Path interface DogApi { @GET("breed/{id}/list") - suspend fun getAllSubBreeds(@Path("id") breed: String): DogSubBreeds + suspend fun getAllSubBreeds(@Path("id") breed: String): DogSubBreedsResponse @GET("breeds/list/all") - suspend fun getAllBreeds(): DogBreeds + suspend fun getAllBreeds(): DogBreedsResponse @GET("breed/{id}}/images") - suspend fun getAllBreeds(@Path("id") breed: String): DogImages + suspend fun getAllImagesForBreed(@Path("id") breed: String): DogImagesResposne @GET("breed/{id}/images/random") - suspend fun getRandomImageForBreed(@Path("id") breed: String): DogMessage + suspend fun getRandomImageForBreed(@Path("id") breed: String): DogImageResponse } -data class DogMessage( +data class DogImageResponse( @JsonProperty("message") val message: String, @@ -27,7 +27,7 @@ data class DogMessage( val status: String ) -data class DogSubBreeds( +data class DogSubBreedsResponse( @JsonProperty("message") val message: List, @@ -35,7 +35,7 @@ data class DogSubBreeds( val status: String ) -data class DogImages( +data class DogImagesResposne( @JsonProperty("message") val message: List, @@ -43,7 +43,7 @@ data class DogImages( val status: String ) -data class DogBreeds( +data class DogBreedsResponse( @JsonProperty("message") val message: Map>, diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsScreenTest.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsScreenTest.kt index 8fadcc36..61c56cc0 100644 --- a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsScreenTest.kt +++ b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogDetailsScreenTest.kt @@ -10,7 +10,7 @@ import com.wealthfront.magellan.lifecycle.transitionToState import com.wealthfront.magellan.sample.migration.AppComponentContainer import com.wealthfront.magellan.sample.migration.TestAppComponent import com.wealthfront.magellan.sample.migration.api.DogApi -import com.wealthfront.magellan.sample.migration.api.DogMessage +import com.wealthfront.magellan.sample.migration.api.DogImageResponse import com.wealthfront.magellan.sample.migration.coWhen import org.junit.Before import org.junit.Rule @@ -30,7 +30,7 @@ import javax.inject.Inject class DogDetailsScreenTest { private lateinit var screen: DogDetailsScreen private val activity = buildActivity(ComponentActivity::class.java).get() - private val breedData = DogMessage( + private val breedData = DogImageResponse( message = "image-url", status = "success" ) diff --git a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt index f664e042..a0eaf370 100644 --- a/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt +++ b/magellan-sample-migration/src/test/java/com/wealthfront/magellan/sample/migration/tide/DogListStepTest.kt @@ -9,7 +9,7 @@ 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.DogApi -import com.wealthfront.magellan.sample.migration.api.DogBreeds +import com.wealthfront.magellan.sample.migration.api.DogBreedsResponse import com.wealthfront.magellan.sample.migration.coWhen import org.junit.Before import org.junit.Test @@ -33,7 +33,7 @@ class DogListStepTest { ((context as AppComponentContainer).injector() as TestAppComponent).inject(this) coWhen { api.getAllBreeds() } - .thenReturn(DogBreeds(message = mapOf("akita" to emptyList()), status = "success")) + .thenReturn(DogBreedsResponse(message = mapOf("akita" to emptyList()), status = "success")) } @Test From 97ca5c52f5975098d7ac61fdcb6df74b0811c643 Mon Sep 17 00:00:00 2001 From: cmathew Date: Thu, 12 Oct 2023 12:06:37 -0700 Subject: [PATCH 6/7] add subbreed endpoint --- .../com/wealthfront/magellan/sample/migration/api/DogApi.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt index 9df777f0..d2992eaf 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/api/DogApi.kt @@ -17,6 +17,12 @@ interface DogApi { @GET("breed/{id}/images/random") suspend fun getRandomImageForBreed(@Path("id") breed: String): DogImageResponse + + @GET("breed/{breed}/{subBreed}/images/random") + suspend fun getRandomImageForSubBreed( + @Path("breed") breed: String, + @Path("subBreed") subBreed: String + ): DogImageResponse } data class DogImageResponse( From 4a10cb7e603a76fea4965bac54bcee3becd1de4d Mon Sep 17 00:00:00 2001 From: cmathew Date: Thu, 12 Oct 2023 13:09:24 -0700 Subject: [PATCH 7/7] move adapter to own clas --- .../sample/migration/tide/DogListAdapter.kt | 36 +++++++++++++++++++ .../sample/migration/tide/DogListStep.kt | 30 ---------------- 2 files changed, 36 insertions(+), 30 deletions(-) create mode 100644 magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListAdapter.kt diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListAdapter.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListAdapter.kt new file mode 100644 index 00000000..4aaf5bd6 --- /dev/null +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListAdapter.kt @@ -0,0 +1,36 @@ +package com.wealthfront.magellan.sample.migration.tide + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.wealthfront.magellan.sample.migration.R + +class DogListAdapter( + private val onDogSelected: (String) -> Unit +) : RecyclerView.Adapter() { + + var dataSet: Array = emptyArray() + + class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + + val textView: TextView = view.findViewById(R.id.dogName) + } + + override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { + val view = LayoutInflater.from(viewGroup.context) + .inflate(R.layout.dog_item, viewGroup, false) + + return ViewHolder(view) + } + + override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { + viewHolder.textView.text = dataSet[position] + viewHolder.itemView.setOnClickListener { + onDogSelected(dataSet[position]) + } + } + + override fun getItemCount() = dataSet.size +} diff --git a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt index 8e75cb59..832e5659 100644 --- a/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt +++ b/magellan-sample-migration/src/main/java/com/wealthfront/magellan/sample/migration/tide/DogListStep.kt @@ -1,15 +1,11 @@ package com.wealthfront.magellan.sample.migration.tide import android.content.Context -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup -import android.widget.TextView import android.widget.Toast import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL -import androidx.recyclerview.widget.RecyclerView import com.wealthfront.magellan.core.Step import com.wealthfront.magellan.sample.migration.AppComponentContainer import com.wealthfront.magellan.sample.migration.R @@ -49,30 +45,4 @@ class DogListStep(private val goToDogDetails: (name: String) -> Unit) : binding.dogItemsLoading.visibility = View.GONE } } - - private class DogListAdapter(private val onDogSelected: (String) -> Unit) : - RecyclerView.Adapter() { - - var dataSet: Array = emptyArray() - - class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { - val textView: TextView = view.findViewById(R.id.dogName) - } - - override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder { - val view = LayoutInflater.from(viewGroup.context) - .inflate(R.layout.dog_item, viewGroup, false) - - return ViewHolder(view) - } - - override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { - viewHolder.textView.text = dataSet[position] - viewHolder.itemView.setOnClickListener { - onDogSelected(dataSet[position]) - } - } - - override fun getItemCount() = dataSet.size - } }