mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-11-03 21:15:35 +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 "androidx.test.ext:junit-ktx:1.1.2"
 | 
			
		||||
    testImplementation "androidx.test:core-ktx:1.3.0"
 | 
			
		||||
    testImplementation "androidx.arch.core:core-testing:2.1.0"
 | 
			
		||||
    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 'com.android.support:support-annotations:28.0.0'
 | 
			
		||||
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
 | 
			
		||||
 | 
			
		||||
@ -382,7 +382,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
 | 
			
		||||
            shouldRefresh = false;
 | 
			
		||||
            return root;
 | 
			
		||||
        }
 | 
			
		||||
        // appStateViewModel.getCurrentUserLiveData().observe(getViewLifecycleOwner(), user -> viewModel.setCurrentUser(user));
 | 
			
		||||
        appStateViewModel.getCurrentUserLiveData().observe(getViewLifecycleOwner(), user -> viewModel.setCurrentUser(user));
 | 
			
		||||
        binding = FragmentProfileBinding.inflate(inflater, container, false);
 | 
			
		||||
        root = binding.getRoot();
 | 
			
		||||
        profileDetailsBinding = binding.header;
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,12 @@
 | 
			
		||||
package awais.instagrabber.viewmodels
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.util.Log
 | 
			
		||||
import androidx.lifecycle.*
 | 
			
		||||
import androidx.savedstate.SavedStateRegistryOwner
 | 
			
		||||
import awais.instagrabber.db.repositories.AccountRepository
 | 
			
		||||
import awais.instagrabber.db.repositories.FavoriteRepository
 | 
			
		||||
import awais.instagrabber.models.Resource
 | 
			
		||||
import awais.instagrabber.repositories.responses.User
 | 
			
		||||
import awais.instagrabber.utils.extensions.TAG
 | 
			
		||||
import awais.instagrabber.webservices.*
 | 
			
		||||
 | 
			
		||||
class ProfileFragmentViewModel(
 | 
			
		||||
@ -20,17 +19,44 @@ class ProfileFragmentViewModel(
 | 
			
		||||
    accountRepository: AccountRepository,
 | 
			
		||||
    favoriteRepository: FavoriteRepository,
 | 
			
		||||
) : ViewModel() {
 | 
			
		||||
    private val _profile = MutableLiveData<User?>()
 | 
			
		||||
    val profile: LiveData<User?> = _profile
 | 
			
		||||
    val username: LiveData<String> = Transformations.map(profile) { return@map it?.username ?: "" }
 | 
			
		||||
    private val _profile = MutableLiveData<Resource<User?>>(Resource.loading(null))
 | 
			
		||||
    private val _isLoggedIn = MutableLiveData(false)
 | 
			
		||||
 | 
			
		||||
    var currentUser: User? = null
 | 
			
		||||
    var isLoggedIn = false
 | 
			
		||||
        get() = currentUser != null
 | 
			
		||||
        private set
 | 
			
		||||
    val profile: LiveData<Resource<User?>> = _profile
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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 {
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
 | 
			
		||||
import androidx.lifecycle.SavedStateHandle
 | 
			
		||||
import androidx.test.ext.junit.runners.AndroidJUnit4
 | 
			
		||||
import awais.instagrabber.common.*
 | 
			
		||||
@ -7,19 +8,49 @@ import awais.instagrabber.db.datasources.AccountDataSource
 | 
			
		||||
import awais.instagrabber.db.datasources.FavoriteDataSource
 | 
			
		||||
import awais.instagrabber.db.repositories.AccountRepository
 | 
			
		||||
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 org.junit.Rule
 | 
			
		||||
import org.junit.Test
 | 
			
		||||
import org.junit.jupiter.api.Assertions.assertEquals
 | 
			
		||||
import org.junit.jupiter.api.Assertions.assertNull
 | 
			
		||||
import org.junit.runner.RunWith
 | 
			
		||||
 | 
			
		||||
@RunWith(AndroidJUnit4::class)
 | 
			
		||||
internal class ProfileFragmentViewModelTest {
 | 
			
		||||
 | 
			
		||||
    @get:Rule
 | 
			
		||||
    var instantExecutorRule = InstantTaskExecutorRule()
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    fun testNoUsernameNoCurrentUser() {
 | 
			
		||||
        val state = SavedStateHandle(
 | 
			
		||||
            mutableMapOf<String, Any>(
 | 
			
		||||
                "username" to ""
 | 
			
		||||
            )
 | 
			
		||||
        val accountDataSource = AccountDataSource(AccountDaoAdapter())
 | 
			
		||||
        val viewModel = ProfileFragmentViewModel(
 | 
			
		||||
            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 friendshipRepository = FriendshipRepository(FriendshipServiceAdapter())
 | 
			
		||||
        val storiesRepository = StoriesRepository(StoriesServiceAdapter())
 | 
			
		||||
@ -29,7 +60,7 @@ internal class ProfileFragmentViewModelTest {
 | 
			
		||||
        val accountRepository = AccountRepository(accountDataSource)
 | 
			
		||||
        val favoriteRepository = FavoriteRepository(FavoriteDataSource(FavoriteDaoAdapter()))
 | 
			
		||||
        val viewModel = ProfileFragmentViewModel(
 | 
			
		||||
            state,
 | 
			
		||||
            SavedStateHandle(),
 | 
			
		||||
            userRepository,
 | 
			
		||||
            friendshipRepository,
 | 
			
		||||
            storiesRepository,
 | 
			
		||||
@ -38,5 +69,11 @@ internal class ProfileFragmentViewModelTest {
 | 
			
		||||
            accountRepository,
 | 
			
		||||
            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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user