Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Verified Commit 45f75c6b authored by Fahim M. Choudhury's avatar Fahim M. Choudhury
Browse files

test: add more unit tests to cover all the scenarios

parent b4eb977c
Loading
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ class GetAppInstallationPermissionUseCaseImpl
constructor(
    private val applicationRepository: ApplicationRepository,
    private val dataStoreManager: DataStoreManager,
    private val contentRatingRepository: GooglePlayContentRatingsRepository,
    private val googlePlayContentRatingsRepository: GooglePlayContentRatingsRepository,
    private val getParentalControlStateUseCase: GetParentalControlStateUseCase,
    private val playStoreRepository: PlayStoreRepository
) : GetAppInstallationPermissionUseCase {
@@ -57,7 +57,7 @@ constructor(
            is AgeGroup ->
                when {
                    isFDroidApp(app) -> validateNsfwAntiFeature(app, parentalControl)
                    else -> validateAgeLimit(app, parentalControl)
                    else -> validateGooglePlayContentRating(app, parentalControl)
                }
        }
    }
@@ -78,19 +78,19 @@ constructor(
    private fun isNsfwFDroidApp(app: AppInstall) =
        app.antiFeatures.any { antiFeature -> antiFeature.containsKey(KEY_ANTI_FEATURES_NSFW) }

    private suspend fun validateAgeLimit(
    private suspend fun validateGooglePlayContentRating(
        app: AppInstall,
        parentalControlState: AgeGroup
    ): AppInstallationPermissionState {

        return when {
            isGPlayApp(app) && hasNoContentRating(app) -> DeniedOnDataLoadError
            hasValidAgeLimit(app, parentalControlState) -> Allowed
            isGooglePlayApp(app) && hasNoContentRating(app) -> DeniedOnDataLoadError
            hasValidContentRating(app, parentalControlState) -> Allowed
            else -> Denied
        }
    }

    private fun isGPlayApp(app: AppInstall): Boolean {
    private fun isGooglePlayApp(app: AppInstall): Boolean {
        return !isFDroidApp(app) && app.type != Type.PWA
    }

@@ -101,17 +101,21 @@ constructor(
        return !verifyContentRatingExists(app, authData)
    }

    private fun hasValidAgeLimit(
    private fun hasValidContentRating(
        app: AppInstall,
        parentalControlState: AgeGroup,
    ): Boolean {
        return when {
            app.contentRating.id.isBlank() -> false
            else -> {
                val allowedContentRatingGroup =
            contentRatingRepository.contentRatingGroups.find {
                    googlePlayContentRatingsRepository.contentRatingGroups.find {
                        it.id == parentalControlState.ageGroup.name
            }
                    } ?: return false

        return (app.contentRating.id.isNotEmpty() &&
            allowedContentRatingGroup?.ratings?.contains(app.contentRating.id) == true)
                allowedContentRatingGroup.ratings.contains(app.contentRating.id)
            }
        }
    }

    private suspend fun verifyContentRatingExists(app: AppInstall, authData: AuthData): Boolean {
+184 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import foundation.e.apps.data.install.models.AppInstall
import foundation.e.apps.data.login.AuthenticatorRepository
import foundation.e.apps.data.parentalcontrol.AppInstallationPermissionState.Allowed
import foundation.e.apps.data.parentalcontrol.AppInstallationPermissionState.Denied
import foundation.e.apps.data.parentalcontrol.AppInstallationPermissionState.DeniedOnDataLoadError
import foundation.e.apps.data.parentalcontrol.GetAppInstallationPermissionUseCaseImpl
import foundation.e.apps.data.parentalcontrol.gplayrating.GooglePlayContentRatingGroup
import foundation.e.apps.data.parentalcontrol.gplayrating.GooglePlayContentRatingsRepository
@@ -38,6 +39,7 @@ import foundation.e.apps.domain.parentalcontrol.GetParentalControlStateUseCase
import foundation.e.apps.domain.parentalcontrol.model.AgeGroupValue
import foundation.e.apps.domain.parentalcontrol.model.ParentalControlState
import foundation.e.apps.util.MainCoroutineRule
import kotlin.test.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -46,9 +48,9 @@ import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import kotlin.test.assertEquals

class GetAppInstallationPermissionUseCaseTest {

    // Run tasks synchronously
    @Rule @JvmField val instantExecutorRule = InstantTaskExecutorRule()

@@ -294,4 +296,185 @@ class GetAppInstallationPermissionUseCaseTest {
            assertEquals(Denied, installationPermissionState)
        }
    }

    @Test
    fun `deny app installation on data load error when parental control is enabled and Google Play app has no content rating`() {
        runTest {
            val appPackage = "com.unit.test"
            val contentRatingTitle = ""
            val contentRatingId = contentRatingTitle.lowercase()

            val googlePlayContentRatingGroup =
                listOf(
                    GooglePlayContentRatingGroup(
                        id = "THREE",
                        ageGroup = "0-3",
                        ratings =
                            listOf("rated for 3+") // ratings will be parsed as lowercase in real
                        ))

            val email = "test@test.com"
            val token = "token"

            val contentRating = ContentRating(title = contentRatingTitle)
            val contentRatingWithId =
                ContentRating(id = contentRatingId, title = contentRatingTitle)

            val appPendingInstallation: AppInstall =
                AppInstall(packageName = appPackage).apply {
                    this.isFDroidApp = false
                    this.contentRating = contentRating
                }

            val application = Application(isFDroidApp = false, contentRating = contentRating)

            val authData = AuthData(email, token)

            Mockito.`when`(getParentalControlStateUseCase.invoke())
                .thenReturn(ParentalControlState.AgeGroup(AgeGroupValue.THREE))

            Mockito.`when`(contentRatingsRepository.contentRatingGroups)
                .thenReturn(googlePlayContentRatingGroup)

            Mockito.`when`(authenticatorRepository.gplayAuth).thenReturn(authData)

            Mockito.`when`(dataStoreManager.getAuthData()).thenReturn(authData)

            Mockito.`when`(
                    applicationRepository.getApplicationDetails(
                        appPendingInstallation.id,
                        appPendingInstallation.packageName,
                        authData,
                        appPendingInstallation.origin))
                .thenReturn(Pair(application, ResultStatus.OK))

            Mockito.`when`(playStoreRepository.getContentRatingWithId(appPackage, contentRating))
                .thenReturn(contentRatingWithId)

            val installationPermissionState = useCase.invoke(appPendingInstallation)

            assertEquals(DeniedOnDataLoadError, installationPermissionState)
        }
    }

    @Test
    fun `deny app installation on data load error when parental control is enabled and Google Play app has no content rating and app details can't be loaded`() {
        runTest {
            val appPackage = "com.unit.test"
            val contentRatingTitle = ""
            val contentRatingId = contentRatingTitle.lowercase()

            val googlePlayContentRatingGroup =
                listOf(
                    GooglePlayContentRatingGroup(
                        id = "THREE",
                        ageGroup = "0-3",
                        ratings =
                            listOf("rated for 3+") // ratings will be parsed as lowercase in real
                        ))

            val email = "test@test.com"
            val token = "token"

            val contentRating = ContentRating(title = contentRatingTitle)
            val contentRatingWithId =
                ContentRating(id = contentRatingId, title = contentRatingTitle)

            val appPendingInstallation: AppInstall =
                AppInstall(packageName = appPackage).apply {
                    this.isFDroidApp = false
                    this.contentRating = contentRating
                }

            val application = Application(isFDroidApp = false, contentRating = contentRating)

            val authData = AuthData(email, token)

            Mockito.`when`(getParentalControlStateUseCase.invoke())
                .thenReturn(ParentalControlState.AgeGroup(AgeGroupValue.THREE))

            Mockito.`when`(contentRatingsRepository.contentRatingGroups)
                .thenReturn(googlePlayContentRatingGroup)

            Mockito.`when`(authenticatorRepository.gplayAuth).thenReturn(authData)

            Mockito.`when`(dataStoreManager.getAuthData()).thenReturn(authData)

            Mockito.`when`(
                    applicationRepository.getApplicationDetails(
                        appPendingInstallation.id,
                        appPendingInstallation.packageName,
                        authData,
                        appPendingInstallation.origin))
                .thenReturn(Pair(application, ResultStatus.UNKNOWN))

            Mockito.`when`(playStoreRepository.getContentRatingWithId(appPackage, contentRating))
                .thenReturn(contentRatingWithId)

            val installationPermissionState = useCase.invoke(appPendingInstallation)

            assertEquals(DeniedOnDataLoadError, installationPermissionState)
        }
    }

    // Note: This case is unlikely to happen
    @Test
    fun `deny app installation when parental control is enabled and parental control state can't match with Google Play content ratings`() {
        runTest {
            val appPackage = "com.unit.test"
            val contentRatingTitle = "Rated for 3+"
            val contentRatingId = contentRatingTitle.lowercase()

            val googlePlayContentRatingGroup =
                listOf(
                    GooglePlayContentRatingGroup(
                        id = "EIGHTEEN",
                        ageGroup = "18+",
                        ratings =
                            listOf("rated for 18+") // ratings will be parsed as lowercase in real
                        ))

            val email = "test@test.com"
            val token = "token"

            val contentRating = ContentRating(title = contentRatingTitle)
            val contentRatingWithId =
                ContentRating(id = contentRatingId, title = contentRatingTitle)

            val appPendingInstallation: AppInstall =
                AppInstall(packageName = appPackage).apply {
                    this.isFDroidApp = false
                    this.contentRating = contentRating
                }

            val application = Application(isFDroidApp = false, contentRating = contentRating)

            val authData = AuthData(email, token)

            Mockito.`when`(getParentalControlStateUseCase.invoke())
                .thenReturn(ParentalControlState.AgeGroup(AgeGroupValue.THREE))

            Mockito.`when`(contentRatingsRepository.contentRatingGroups)
                .thenReturn(googlePlayContentRatingGroup)

            Mockito.`when`(authenticatorRepository.gplayAuth).thenReturn(authData)

            Mockito.`when`(dataStoreManager.getAuthData()).thenReturn(authData)

            Mockito.`when`(
                    applicationRepository.getApplicationDetails(
                        appPendingInstallation.id,
                        appPendingInstallation.packageName,
                        authData,
                        appPendingInstallation.origin))
                .thenReturn(Pair(application, ResultStatus.UNKNOWN))

            Mockito.`when`(playStoreRepository.getContentRatingWithId(appPackage, contentRating))
                .thenReturn(contentRatingWithId)

            val installationPermissionState = useCase.invoke(appPendingInstallation)

            assertEquals(Denied, installationPermissionState)
        }
    }
}