mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-15 19:27:31 +00:00
Add some ProfileFragmentViewModel logic and tests
This commit is contained in:
parent
1d9eb43442
commit
70ffac3025
@ -242,9 +242,10 @@ dependencies {
|
|||||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
|
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
|
||||||
testImplementation "androidx.test.ext:junit-ktx:1.1.2"
|
testImplementation "androidx.test.ext:junit-ktx:1.1.2"
|
||||||
testImplementation "androidx.test:core-ktx:1.3.0"
|
testImplementation "androidx.test:core-ktx:1.3.0"
|
||||||
|
testImplementation "androidx.arch.core:core-testing:2.1.0"
|
||||||
testImplementation "org.robolectric:robolectric:4.5.1"
|
testImplementation "org.robolectric:robolectric:4.5.1"
|
||||||
|
|
||||||
androidTestImplementation 'org.junit.jupiter:junit-jupiter:5.7.1'
|
androidTestImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
|
||||||
androidTestImplementation 'androidx.test:core:1.3.0'
|
androidTestImplementation 'androidx.test:core:1.3.0'
|
||||||
androidTestImplementation 'com.android.support:support-annotations:28.0.0'
|
androidTestImplementation 'com.android.support:support-annotations:28.0.0'
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
|
@ -382,7 +382,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
|||||||
shouldRefresh = false;
|
shouldRefresh = false;
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
// appStateViewModel.getCurrentUserLiveData().observe(getViewLifecycleOwner(), user -> viewModel.setCurrentUser(user));
|
appStateViewModel.getCurrentUserLiveData().observe(getViewLifecycleOwner(), user -> viewModel.setCurrentUser(user));
|
||||||
binding = FragmentProfileBinding.inflate(inflater, container, false);
|
binding = FragmentProfileBinding.inflate(inflater, container, false);
|
||||||
root = binding.getRoot();
|
root = binding.getRoot();
|
||||||
profileDetailsBinding = binding.header;
|
profileDetailsBinding = binding.header;
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
package awais.instagrabber.viewmodels
|
package awais.instagrabber.viewmodels
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
import androidx.savedstate.SavedStateRegistryOwner
|
import androidx.savedstate.SavedStateRegistryOwner
|
||||||
import awais.instagrabber.db.repositories.AccountRepository
|
import awais.instagrabber.db.repositories.AccountRepository
|
||||||
import awais.instagrabber.db.repositories.FavoriteRepository
|
import awais.instagrabber.db.repositories.FavoriteRepository
|
||||||
|
import awais.instagrabber.models.Resource
|
||||||
import awais.instagrabber.repositories.responses.User
|
import awais.instagrabber.repositories.responses.User
|
||||||
import awais.instagrabber.utils.extensions.TAG
|
|
||||||
import awais.instagrabber.webservices.*
|
import awais.instagrabber.webservices.*
|
||||||
|
|
||||||
class ProfileFragmentViewModel(
|
class ProfileFragmentViewModel(
|
||||||
@ -20,17 +19,44 @@ class ProfileFragmentViewModel(
|
|||||||
accountRepository: AccountRepository,
|
accountRepository: AccountRepository,
|
||||||
favoriteRepository: FavoriteRepository,
|
favoriteRepository: FavoriteRepository,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private val _profile = MutableLiveData<User?>()
|
private val _profile = MutableLiveData<Resource<User?>>(Resource.loading(null))
|
||||||
val profile: LiveData<User?> = _profile
|
private val _isLoggedIn = MutableLiveData(false)
|
||||||
val username: LiveData<String> = Transformations.map(profile) { return@map it?.username ?: "" }
|
|
||||||
|
|
||||||
var currentUser: User? = null
|
val profile: LiveData<Resource<User?>> = _profile
|
||||||
var isLoggedIn = false
|
|
||||||
get() = currentUser != null
|
/**
|
||||||
private set
|
* Username of profile without '`@`'
|
||||||
|
*/
|
||||||
|
val username: LiveData<String> = Transformations.map(profile) {
|
||||||
|
return@map when (it.status) {
|
||||||
|
Resource.Status.LOADING, Resource.Status.ERROR -> ""
|
||||||
|
Resource.Status.SUCCESS -> it.data?.username ?: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val isLoggedIn: LiveData<Boolean> = _isLoggedIn
|
||||||
|
|
||||||
|
var currentUser: Resource<User?>? = null
|
||||||
|
set(value) {
|
||||||
|
_isLoggedIn.postValue(value?.data != null)
|
||||||
|
// if no profile, and value is valid, set it as profile
|
||||||
|
val profileValue = profile.value
|
||||||
|
if (
|
||||||
|
profileValue?.status != Resource.Status.LOADING
|
||||||
|
&& profileValue?.data == null
|
||||||
|
&& value?.status == Resource.Status.SUCCESS
|
||||||
|
&& value.data != null
|
||||||
|
) {
|
||||||
|
_profile.postValue(Resource.success(value.data))
|
||||||
|
}
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
Log.d(TAG, "${state.keys()} $userRepository $friendshipRepository $storiesRepository $mediaRepository")
|
// Log.d(TAG, "${state.keys()} $userRepository $friendshipRepository $storiesRepository $mediaRepository")
|
||||||
|
val usernameFromState = state.get<String?>("username")
|
||||||
|
if (usernameFromState.isNullOrBlank()) {
|
||||||
|
_profile.postValue(Resource.success(null))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
app/src/test/java/awais/instagrabber/LiveDataTestUtil.kt
Normal file
41
app/src/test/java/awais/instagrabber/LiveDataTestUtil.kt
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package awais.instagrabber
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import java.util.concurrent.CountDownLatch
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import java.util.concurrent.TimeoutException
|
||||||
|
|
||||||
|
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
|
||||||
|
fun <T> LiveData<T>.getOrAwaitValue(
|
||||||
|
time: Long = 2,
|
||||||
|
timeUnit: TimeUnit = TimeUnit.SECONDS,
|
||||||
|
afterObserve: () -> Unit = {}
|
||||||
|
): T {
|
||||||
|
var data: T? = null
|
||||||
|
val latch = CountDownLatch(1)
|
||||||
|
val observer = object : Observer<T> {
|
||||||
|
override fun onChanged(o: T?) {
|
||||||
|
data = o
|
||||||
|
latch.countDown()
|
||||||
|
this@getOrAwaitValue.removeObserver(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.observeForever(observer)
|
||||||
|
|
||||||
|
try {
|
||||||
|
afterObserve.invoke()
|
||||||
|
|
||||||
|
// Don't wait indefinitely if the LiveData is not set.
|
||||||
|
if (!latch.await(time, timeUnit)) {
|
||||||
|
throw TimeoutException("LiveData value was never set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
this.removeObserver(observer)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return data as T
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package awais.instagrabber.viewmodels
|
package awais.instagrabber.viewmodels
|
||||||
|
|
||||||
|
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import awais.instagrabber.common.*
|
import awais.instagrabber.common.*
|
||||||
@ -7,19 +8,49 @@ import awais.instagrabber.db.datasources.AccountDataSource
|
|||||||
import awais.instagrabber.db.datasources.FavoriteDataSource
|
import awais.instagrabber.db.datasources.FavoriteDataSource
|
||||||
import awais.instagrabber.db.repositories.AccountRepository
|
import awais.instagrabber.db.repositories.AccountRepository
|
||||||
import awais.instagrabber.db.repositories.FavoriteRepository
|
import awais.instagrabber.db.repositories.FavoriteRepository
|
||||||
|
import awais.instagrabber.getOrAwaitValue
|
||||||
|
import awais.instagrabber.models.Resource
|
||||||
|
import awais.instagrabber.repositories.responses.User
|
||||||
import awais.instagrabber.webservices.*
|
import awais.instagrabber.webservices.*
|
||||||
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertNull
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
internal class ProfileFragmentViewModelTest {
|
internal class ProfileFragmentViewModelTest {
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
var instantExecutorRule = InstantTaskExecutorRule()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNoUsernameNoCurrentUser() {
|
fun testNoUsernameNoCurrentUser() {
|
||||||
val state = SavedStateHandle(
|
val accountDataSource = AccountDataSource(AccountDaoAdapter())
|
||||||
mutableMapOf<String, Any>(
|
val viewModel = ProfileFragmentViewModel(
|
||||||
"username" to ""
|
SavedStateHandle(),
|
||||||
)
|
UserRepository(UserServiceAdapter()),
|
||||||
|
FriendshipRepository(FriendshipServiceAdapter()),
|
||||||
|
StoriesRepository(StoriesServiceAdapter()),
|
||||||
|
MediaRepository(MediaServiceAdapter()),
|
||||||
|
GraphQLRepository(GraphQLServiceAdapter()),
|
||||||
|
AccountRepository(accountDataSource),
|
||||||
|
FavoriteRepository(FavoriteDataSource(FavoriteDaoAdapter()))
|
||||||
)
|
)
|
||||||
|
assertEquals(false, viewModel.isLoggedIn.getOrAwaitValue())
|
||||||
|
assertNull(viewModel.profile.getOrAwaitValue().data)
|
||||||
|
assertEquals("", viewModel.username.getOrAwaitValue())
|
||||||
|
viewModel.currentUser = Resource.success(null)
|
||||||
|
assertEquals(false, viewModel.isLoggedIn.getOrAwaitValue())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNoUsernameWithCurrentUser() {
|
||||||
|
// val state = SavedStateHandle(
|
||||||
|
// mutableMapOf<String, Any?>(
|
||||||
|
// "username" to "test"
|
||||||
|
// )
|
||||||
|
// )
|
||||||
val userRepository = UserRepository(UserServiceAdapter())
|
val userRepository = UserRepository(UserServiceAdapter())
|
||||||
val friendshipRepository = FriendshipRepository(FriendshipServiceAdapter())
|
val friendshipRepository = FriendshipRepository(FriendshipServiceAdapter())
|
||||||
val storiesRepository = StoriesRepository(StoriesServiceAdapter())
|
val storiesRepository = StoriesRepository(StoriesServiceAdapter())
|
||||||
@ -29,7 +60,7 @@ internal class ProfileFragmentViewModelTest {
|
|||||||
val accountRepository = AccountRepository(accountDataSource)
|
val accountRepository = AccountRepository(accountDataSource)
|
||||||
val favoriteRepository = FavoriteRepository(FavoriteDataSource(FavoriteDaoAdapter()))
|
val favoriteRepository = FavoriteRepository(FavoriteDataSource(FavoriteDaoAdapter()))
|
||||||
val viewModel = ProfileFragmentViewModel(
|
val viewModel = ProfileFragmentViewModel(
|
||||||
state,
|
SavedStateHandle(),
|
||||||
userRepository,
|
userRepository,
|
||||||
friendshipRepository,
|
friendshipRepository,
|
||||||
storiesRepository,
|
storiesRepository,
|
||||||
@ -38,5 +69,11 @@ internal class ProfileFragmentViewModelTest {
|
|||||||
accountRepository,
|
accountRepository,
|
||||||
favoriteRepository
|
favoriteRepository
|
||||||
)
|
)
|
||||||
|
assertEquals(false, viewModel.isLoggedIn.getOrAwaitValue())
|
||||||
|
assertNull(viewModel.profile.getOrAwaitValue().data)
|
||||||
|
val user = User()
|
||||||
|
viewModel.currentUser = Resource.success(user)
|
||||||
|
assertEquals(true, viewModel.isLoggedIn.getOrAwaitValue())
|
||||||
|
assertEquals(user, viewModel.profile.getOrAwaitValue().data)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user