From d2b702846e816fb66a05a22c351922f918da0df2 Mon Sep 17 00:00:00 2001 From: mtgriego Date: Tue, 23 Jul 2024 13:12:48 -0700 Subject: [PATCH] [MBL-821] Upgrade profile activity to RX2 (#2078) * upgrade profile activity to RX2 * clear disposables --------- Co-authored-by: Leigh Douglas --- .../ui/activities/ProfileActivity.kt | 81 ++++++++------ .../kickstarter/ui/extensions/ActivityExt.kt | 12 ++- .../viewmodels/ProfileViewModel.kt | 77 ++++++++----- .../viewmodels/ProfileViewModelTest.kt | 102 +++++++++++------- 4 files changed, 171 insertions(+), 101 deletions(-) diff --git a/app/src/main/java/com/kickstarter/ui/activities/ProfileActivity.kt b/app/src/main/java/com/kickstarter/ui/activities/ProfileActivity.kt index 1b8b525656..2c0338fd7a 100644 --- a/app/src/main/java/com/kickstarter/ui/activities/ProfileActivity.kt +++ b/app/src/main/java/com/kickstarter/ui/activities/ProfileActivity.kt @@ -2,126 +2,138 @@ package com.kickstarter.ui.activities import android.content.Intent import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.viewModels import androidx.core.view.isGone import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import com.kickstarter.R import com.kickstarter.databinding.ProfileLayoutBinding -import com.kickstarter.libs.BaseActivity -import com.kickstarter.libs.RecyclerViewPaginator -import com.kickstarter.libs.qualifiers.RequiresActivityViewModel -import com.kickstarter.libs.rx.transformers.Transformers.observeForUI +import com.kickstarter.libs.recyclerviewpagination.RecyclerViewPaginatorV2 +import com.kickstarter.libs.rx.transformers.Transformers.observeForUIV2 import com.kickstarter.libs.utils.ApplicationUtils import com.kickstarter.libs.utils.ViewUtils +import com.kickstarter.libs.utils.extensions.addToDisposable +import com.kickstarter.libs.utils.extensions.getEnvironment import com.kickstarter.libs.utils.extensions.getProjectIntent import com.kickstarter.models.Project import com.kickstarter.ui.IntentKey import com.kickstarter.ui.adapters.ProfileAdapter import com.kickstarter.ui.extensions.loadCircleImage +import com.kickstarter.ui.extensions.startActivityWithTransition import com.kickstarter.viewmodels.ProfileViewModel +import io.reactivex.disposables.CompositeDisposable -@RequiresActivityViewModel(ProfileViewModel.ViewModel::class) -class ProfileActivity : BaseActivity() { +class ProfileActivity : ComponentActivity() { private lateinit var adapter: ProfileAdapter - private lateinit var paginator: RecyclerViewPaginator + private lateinit var paginator: RecyclerViewPaginatorV2 private lateinit var binding: ProfileLayoutBinding + private lateinit var profileViewModelFactory: ProfileViewModel.Factory + private val viewModel: ProfileViewModel.ProfileViewModel by viewModels { profileViewModelFactory } + + private val disposables = CompositeDisposable() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ProfileLayoutBinding.inflate(layoutInflater) setContentView(binding.root) + getEnvironment()?.let { env -> + profileViewModelFactory = ProfileViewModel.Factory(env) + } + this.adapter = ProfileAdapter(this.viewModel) val spanCount = if (ViewUtils.isLandscape(this)) 3 else 2 binding.recyclerView.layoutManager = GridLayoutManager(this, spanCount) binding.recyclerView.adapter = this.adapter - this.paginator = RecyclerViewPaginator( + this.paginator = RecyclerViewPaginatorV2( binding.recyclerView, { this.viewModel.inputs.nextPage() }, this.viewModel.outputs.isFetchingProjects() ) this.viewModel.outputs.avatarImageViewUrl() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { url -> binding.avatarImageView.loadCircleImage(url) } + .addToDisposable(disposables) this.viewModel.outputs.backedCountTextViewHidden() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { binding.backedCountTextView.isGone = it } + .addToDisposable(disposables) this.viewModel.outputs.backedCountTextViewText() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { binding.backedCountTextView.text = it } + .addToDisposable(disposables) this.viewModel.outputs.backedTextViewHidden() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { binding.backedTextView.isGone = it } + .addToDisposable(disposables) this.viewModel.outputs.createdCountTextViewHidden() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { binding.createdCountTextView.isGone = it } + .addToDisposable(disposables) this.viewModel.outputs.createdCountTextViewText() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { binding.createdCountTextView.text = it } + .addToDisposable(disposables) this.viewModel.outputs.createdTextViewHidden() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { binding.createdTextView.isGone = it } + .addToDisposable(disposables) this.viewModel.outputs.dividerViewHidden() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { binding.dividerView.isGone = it } + .addToDisposable(disposables) this.viewModel.outputs.projectList() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { this.loadProjects(it) } + .addToDisposable(disposables) this.viewModel.outputs.resumeDiscoveryActivity() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { resumeDiscoveryActivity() } + .addToDisposable(disposables) this.viewModel.outputs.startMessageThreadsActivity() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { this.startMessageThreadsActivity() } + .addToDisposable(disposables) this.viewModel.outputs.startProjectActivity() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { this.startProjectActivity(it) } + .addToDisposable(disposables) this.viewModel.outputs.userNameTextViewText() - .compose(bindToLifecycle()) - .compose(observeForUI()) + .compose(observeForUIV2()) .subscribe { binding.userNameTextView.text = it } + .addToDisposable(disposables) binding.profileActivityToolbar.messagesButton.setOnClickListener { this.viewModel.inputs.messagesButtonClicked() } } @@ -130,6 +142,7 @@ class ProfileActivity : BaseActivity() { super.onDestroy() this.paginator.stop() binding.recyclerView.adapter = null + disposables.clear() } private fun loadProjects(projects: List) { diff --git a/app/src/main/java/com/kickstarter/ui/extensions/ActivityExt.kt b/app/src/main/java/com/kickstarter/ui/extensions/ActivityExt.kt index f88419fc0d..1b71147c7a 100644 --- a/app/src/main/java/com/kickstarter/ui/extensions/ActivityExt.kt +++ b/app/src/main/java/com/kickstarter/ui/extensions/ActivityExt.kt @@ -5,9 +5,11 @@ import android.app.Activity import android.content.Context import android.content.Intent import android.net.Uri +import android.os.Build import android.util.Pair import android.view.View import android.view.inputmethod.InputMethodManager +import androidx.activity.ComponentActivity import androidx.activity.result.ActivityResultLauncher import androidx.annotation.AnimRes import androidx.fragment.app.Fragment @@ -50,7 +52,15 @@ fun Activity.startActivityWithTransition( @AnimRes exitAnim: Int ) { startActivity(intent) - overridePendingTransition(enterAnim, exitAnim) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + overrideActivityTransition( + ComponentActivity.OVERRIDE_TRANSITION_OPEN, + enterAnim, + exitAnim + ) + } else { + overridePendingTransition(enterAnim, exitAnim) + } } fun Activity.hideKeyboard() { diff --git a/app/src/main/java/com/kickstarter/viewmodels/ProfileViewModel.kt b/app/src/main/java/com/kickstarter/viewmodels/ProfileViewModel.kt index 76de92a29a..fc9cd2bb89 100644 --- a/app/src/main/java/com/kickstarter/viewmodels/ProfileViewModel.kt +++ b/app/src/main/java/com/kickstarter/viewmodels/ProfileViewModel.kt @@ -1,24 +1,26 @@ package com.kickstarter.viewmodels import android.util.Pair -import com.kickstarter.libs.ActivityViewModel -import com.kickstarter.libs.ApiPaginator +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.kickstarter.libs.ApiPaginatorV2 import com.kickstarter.libs.Environment -import com.kickstarter.libs.rx.transformers.Transformers.neverError +import com.kickstarter.libs.rx.transformers.Transformers.neverErrorV2 import com.kickstarter.libs.utils.EventContextValues import com.kickstarter.libs.utils.NumberUtils +import com.kickstarter.libs.utils.extensions.addToDisposable import com.kickstarter.libs.utils.extensions.isNonZero import com.kickstarter.libs.utils.extensions.isZero import com.kickstarter.models.Project import com.kickstarter.services.DiscoveryParams import com.kickstarter.services.apiresponses.DiscoverEnvelope -import com.kickstarter.ui.activities.ProfileActivity import com.kickstarter.ui.adapters.ProfileAdapter import com.kickstarter.ui.viewholders.EmptyProfileViewHolder import com.kickstarter.ui.viewholders.ProfileCardViewHolder -import rx.Observable -import rx.subjects.BehaviorSubject -import rx.subjects.PublishSubject +import io.reactivex.Observable +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.subjects.BehaviorSubject +import io.reactivex.subjects.PublishSubject interface ProfileViewModel { @@ -68,10 +70,10 @@ interface ProfileViewModel { fun projectList(): Observable> /** Emits when we should resume the [com.kickstarter.ui.activities.DiscoveryActivity]. */ - fun resumeDiscoveryActivity(): Observable + fun resumeDiscoveryActivity(): Observable /** Emits when we should start the [com.kickstarter.ui.activities.MessageThreadsActivity]. */ - fun startMessageThreadsActivity(): Observable + fun startMessageThreadsActivity(): Observable /** Emits when we should start the [com.kickstarter.ui.activities.ProjectActivity]. */ fun startProjectActivity(): Observable @@ -80,13 +82,15 @@ interface ProfileViewModel { fun userNameTextViewText(): Observable } - class ViewModel(environment: Environment) : ActivityViewModel(environment), ProfileAdapter.Delegate, Inputs, Outputs { - private val client = requireNotNull(environment.apiClient()) - private val currentUser = requireNotNull(environment.currentUser()) + class ProfileViewModel(environment: Environment) : ViewModel(), ProfileAdapter.Delegate, Inputs, Outputs { + private val client = requireNotNull(environment.apiClientV2()) + private val currentUser = requireNotNull(environment.currentUserV2()) + private val analytics = requireNotNull(environment.analytics()) - private val exploreProjectsButtonClicked = PublishSubject.create() - private val messagesButtonClicked = PublishSubject.create() - private val nextPage = PublishSubject.create() + private val exploreProjectsButtonClicked = PublishSubject.create() + private val messagesButtonClicked = PublishSubject.create() + private val nextPage = PublishSubject.create() + private val refresh = PublishSubject.create() private val projectCardClicked = PublishSubject.create() private val avatarImageViewUrl: Observable @@ -99,19 +103,22 @@ interface ProfileViewModel { private val dividerViewHidden: Observable private val isFetchingProjects = BehaviorSubject.create() private val projectList: Observable> - private val resumeDiscoveryActivity: Observable - private val startMessageThreadsActivity: Observable + private val resumeDiscoveryActivity: Observable + private val startMessageThreadsActivity: Observable private val userNameTextViewText: Observable val inputs: Inputs = this val outputs: Outputs = this - init { + val disposables = CompositeDisposable() + init { val freshUser = this.client.fetchCurrentUser() .retry(2) - .compose(neverError()) + .compose(neverErrorV2()) + freshUser.subscribe { this.currentUser.refresh(it) } + .addToDisposable(disposables) val params = DiscoveryParams.builder() .backed(1) @@ -119,16 +126,16 @@ interface ProfileViewModel { .sort(DiscoveryParams.Sort.ENDING_SOON) .build() - val paginator = ApiPaginator.builder() - .nextPage(this.nextPage) + val paginator = ApiPaginatorV2.builder() + .nextPage(nextPage) + .startOverWith(Observable.just(params)) .envelopeToListOfData { it.projects() } .envelopeToMoreUrl { env -> env.urls()?.api()?.moreProjects() } - .loadWithParams { this.client.fetchProjects(params).compose(neverError()) } - .loadWithPaginationPath { this.client.fetchProjects(it).compose(neverError()) } + .loadWithParams { this.client.fetchProjects(params).compose(neverErrorV2()) } + .loadWithPaginationPath { this.client.fetchProjects(it).compose(neverErrorV2()) } .build() paginator.isFetching - .compose(bindToLifecycle()) .subscribe(this.isFetchingProjects) val loggedInUser = this.currentUser.loggedInUser() @@ -166,17 +173,17 @@ interface ProfileViewModel { this.userNameTextViewText = loggedInUser.map { it.name() } projectCardClicked - .compose(bindToLifecycle()) - .subscribe { analyticEvents.trackProjectCardClicked(it, EventContextValues.ContextPageName.PROFILE.contextName) } + .subscribe { analytics.trackProjectCardClicked(it, EventContextValues.ContextPageName.PROFILE.contextName) } + .addToDisposable(disposables) } override fun emptyProfileViewHolderExploreProjectsClicked(viewHolder: EmptyProfileViewHolder) = this.exploreProjectsButtonClicked() - override fun exploreProjectsButtonClicked() = this.exploreProjectsButtonClicked.onNext(null) + override fun exploreProjectsButtonClicked() = this.exploreProjectsButtonClicked.onNext(Unit) - override fun messagesButtonClicked() = this.messagesButtonClicked.onNext(null) + override fun messagesButtonClicked() = this.messagesButtonClicked.onNext(Unit) - override fun nextPage() = this.nextPage.onNext(null) + override fun nextPage() = this.nextPage.onNext(Unit) override fun profileCardViewHolderClicked(viewHolder: ProfileCardViewHolder, project: Project) = this.projectCardClicked(project) @@ -209,5 +216,17 @@ interface ProfileViewModel { override fun startMessageThreadsActivity() = this.startMessageThreadsActivity override fun userNameTextViewText() = this.userNameTextViewText + + override fun onCleared() { + disposables.clear() + super.onCleared() + } + } + + class Factory(private val environment: Environment) : + ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + return ProfileViewModel(environment) as T + } } } diff --git a/app/src/test/java/com/kickstarter/viewmodels/ProfileViewModelTest.kt b/app/src/test/java/com/kickstarter/viewmodels/ProfileViewModelTest.kt index cc32b593d3..52d786bb0f 100644 --- a/app/src/test/java/com/kickstarter/viewmodels/ProfileViewModelTest.kt +++ b/app/src/test/java/com/kickstarter/viewmodels/ProfileViewModelTest.kt @@ -5,20 +5,23 @@ import com.kickstarter.libs.Environment import com.kickstarter.libs.MockCurrentUser import com.kickstarter.libs.utils.EventName import com.kickstarter.libs.utils.NumberUtils +import com.kickstarter.libs.utils.extensions.addToDisposable import com.kickstarter.mock.factories.DiscoverEnvelopeFactory import com.kickstarter.mock.factories.ProjectFactory import com.kickstarter.mock.factories.UserFactory -import com.kickstarter.mock.services.MockApiClient +import com.kickstarter.mock.services.MockApiClientV2 import com.kickstarter.models.Project import com.kickstarter.models.User import com.kickstarter.services.DiscoveryParams import com.kickstarter.services.apiresponses.DiscoverEnvelope +import io.reactivex.Observable +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.subscribers.TestSubscriber +import org.junit.After import org.junit.Test -import rx.Observable -import rx.observers.TestSubscriber class ProfileViewModelTest : KSRobolectricTestCase() { - private lateinit var vm: ProfileViewModel.ViewModel + private lateinit var vm: ProfileViewModel.ProfileViewModel private val avatarImageViewUrl = TestSubscriber() private val backedCountTextViewHidden = TestSubscriber() private val backedCountTextViewText = TestSubscriber() @@ -28,27 +31,47 @@ class ProfileViewModelTest : KSRobolectricTestCase() { private val createdTextViewHidden = TestSubscriber() private val dividerViewHidden = TestSubscriber() private val projectList = TestSubscriber>() - private val resumeDiscoveryActivity = TestSubscriber() - private val startMessageThreadsActivity = TestSubscriber() + private val resumeDiscoveryActivity = TestSubscriber() + private val startMessageThreadsActivity = TestSubscriber() private val startProjectActivity = TestSubscriber() private val userNameTextViewText = TestSubscriber() + private val disposables = CompositeDisposable() + private fun setUpEnvironment(environment: Environment) { - this.vm = ProfileViewModel.ViewModel(environment) - - this.vm.outputs.avatarImageViewUrl().subscribe(this.avatarImageViewUrl) - this.vm.outputs.backedCountTextViewHidden().subscribe(this.backedCountTextViewHidden) - this.vm.outputs.backedCountTextViewText().subscribe(this.backedCountTextViewText) - this.vm.outputs.backedTextViewHidden().subscribe(this.backedTextViewHidden) - this.vm.outputs.createdCountTextViewHidden().subscribe(this.createdCountTextViewHidden) - this.vm.outputs.createdCountTextViewText().subscribe(this.createdCountTextViewText) - this.vm.outputs.createdTextViewHidden().subscribe(this.createdTextViewHidden) - this.vm.outputs.dividerViewHidden().subscribe(this.dividerViewHidden) - this.vm.outputs.projectList().subscribe(this.projectList) - this.vm.outputs.resumeDiscoveryActivity().subscribe(this.resumeDiscoveryActivity) - this.vm.outputs.startMessageThreadsActivity().subscribe(this.startMessageThreadsActivity) - this.vm.outputs.startProjectActivity().subscribe(this.startProjectActivity) - this.vm.outputs.userNameTextViewText().subscribe(this.userNameTextViewText) + this.vm = ProfileViewModel.ProfileViewModel(environment) + + this.vm.outputs.avatarImageViewUrl().subscribe { this.avatarImageViewUrl.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.backedCountTextViewHidden() + .subscribe { this.backedCountTextViewHidden.onNext(it) }.addToDisposable(disposables) + this.vm.outputs.backedCountTextViewText() + .subscribe { this.backedCountTextViewText.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.backedTextViewHidden().subscribe { this.backedTextViewHidden.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.createdCountTextViewHidden() + .subscribe { this.createdCountTextViewHidden.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.createdCountTextViewText() + .subscribe { this.createdCountTextViewText.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.createdTextViewHidden().subscribe { this.createdTextViewHidden.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.dividerViewHidden().subscribe { this.dividerViewHidden.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.projectList().subscribe { this.projectList.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.resumeDiscoveryActivity() + .subscribe { this.resumeDiscoveryActivity.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.startMessageThreadsActivity() + .subscribe { this.startMessageThreadsActivity.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.startProjectActivity().subscribe { this.startProjectActivity.onNext(it) } + .addToDisposable(disposables) + this.vm.outputs.userNameTextViewText().subscribe { this.userNameTextViewText.onNext(it) } + .addToDisposable(disposables) } @Test @@ -58,22 +81,22 @@ class ProfileViewModelTest : KSRobolectricTestCase() { .createdProjectsCount(2) .build() - val apiClient = object : MockApiClient() { + val apiClient = object : MockApiClientV2() { override fun fetchCurrentUser(): Observable { return Observable.just(user) } } - setUpEnvironment(environment().toBuilder().apiClient(apiClient).build()) + setUpEnvironment(environment().toBuilder().apiClientV2(apiClient).build()) // Backed text views are displayed. this.backedCountTextViewHidden.assertValues(false) - this.backedCountTextViewText.assertValues(NumberUtils.format(user.backedProjectsCount()!!)) + this.backedCountTextViewText.assertValues(NumberUtils.format(user.backedProjectsCount())) this.backedTextViewHidden.assertValues(false) // Created text views are displayed. this.createdCountTextViewHidden.assertValues(false) - this.createdCountTextViewText.assertValues(NumberUtils.format(user.createdProjectsCount()!!)) + this.createdCountTextViewText.assertValues(NumberUtils.format(user.createdProjectsCount())) this.createdTextViewHidden.assertValues(false) // Divider view is displayed. @@ -87,17 +110,17 @@ class ProfileViewModelTest : KSRobolectricTestCase() { .createdProjectsCount(0) .build() - val apiClient = object : MockApiClient() { + val apiClient = object : MockApiClientV2() { override fun fetchCurrentUser(): Observable { return Observable.just(user) } } - setUpEnvironment(environment().toBuilder().apiClient(apiClient).build()) + setUpEnvironment(environment().toBuilder().apiClientV2(apiClient).build()) // Backed text views are displayed. this.backedCountTextViewHidden.assertValues(false) - this.backedCountTextViewText.assertValues(NumberUtils.format(user.backedProjectsCount()!!)) + this.backedCountTextViewText.assertValues(NumberUtils.format(user.backedProjectsCount())) this.backedTextViewHidden.assertValues(false) // Created text views are hidden. @@ -116,13 +139,13 @@ class ProfileViewModelTest : KSRobolectricTestCase() { .createdProjectsCount(2) .build() - val apiClient = object : MockApiClient() { + val apiClient = object : MockApiClientV2() { override fun fetchCurrentUser(): Observable { return Observable.just(user) } } - setUpEnvironment(environment().toBuilder().apiClient(apiClient).build()) + setUpEnvironment(environment().toBuilder().apiClientV2(apiClient).build()) // Backed text views are hidden. this.backedCountTextViewHidden.assertValues(true) @@ -131,7 +154,7 @@ class ProfileViewModelTest : KSRobolectricTestCase() { // Created text views are displayed. this.createdCountTextViewHidden.assertValues(false) - this.createdCountTextViewText.assertValues(NumberUtils.format(user.createdProjectsCount()!!)) + this.createdCountTextViewText.assertValues(NumberUtils.format(user.createdProjectsCount())) this.createdTextViewHidden.assertValues(false) // Divider view is hidden. @@ -140,7 +163,7 @@ class ProfileViewModelTest : KSRobolectricTestCase() { @Test fun testProfileViewModel_EmitsProjects() { - val apiClient = object : MockApiClient() { + val apiClient = object : MockApiClientV2() { override fun fetchProjects(params: DiscoveryParams): Observable { return Observable.just( DiscoverEnvelopeFactory.discoverEnvelope(listOf(ProjectFactory.project())) @@ -148,7 +171,7 @@ class ProfileViewModelTest : KSRobolectricTestCase() { } } - setUpEnvironment(environment().toBuilder().apiClient(apiClient).build()) + setUpEnvironment(environment().toBuilder().apiClientV2(apiClient).build()) this.projectList.assertValueCount(1) } @@ -156,13 +179,13 @@ class ProfileViewModelTest : KSRobolectricTestCase() { @Test fun testProfileViewModel_EmitsUserNameAndAvatar() { val user = UserFactory.user() - val apiClient = object : MockApiClient() { + val apiClient = object : MockApiClientV2() { override fun fetchCurrentUser(): Observable { return Observable.just(user) } } - setUpEnvironment(environment().toBuilder().apiClient(apiClient).build()) + setUpEnvironment(environment().toBuilder().apiClientV2(apiClient).build()) this.avatarImageViewUrl.assertValues(user.avatar().medium()) this.userNameTextViewText.assertValues(user.name()) @@ -191,7 +214,7 @@ class ProfileViewModelTest : KSRobolectricTestCase() { val project = ProjectFactory.project() this.vm.inputs.projectCardClicked(project) this.startProjectActivity.assertValueCount(1) - assertEquals(this.startProjectActivity.onNextEvents[0], project) + assertEquals(this.startProjectActivity.values().first(), project) this.segmentTrack.assertValue(EventName.CARD_CLICKED.eventName) } @@ -208,7 +231,12 @@ class ProfileViewModelTest : KSRobolectricTestCase() { val project = ProjectFactory.project() this.vm.inputs.projectCardClicked(project) this.startProjectActivity.assertValueCount(1) - assertEquals(this.startProjectActivity.onNextEvents[0], project) + assertEquals(this.startProjectActivity.values().first(), project) this.segmentTrack.assertValue(EventName.CARD_CLICKED.eventName) } + + @After + fun clear() { + disposables.clear() + } }