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

Commit 3edcb7c7 authored by Jonathan Klee's avatar Jonathan Klee
Browse files

tests: add more unit tests

parent 1581a892
Loading
Loading
Loading
Loading
Loading
+121 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2026 e Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package foundation.e.apps.data.login.repository

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.aurora.gplayapi.data.models.AuthData
import com.google.common.truth.Truth.assertThat
import foundation.e.apps.data.ResultSupreme
import foundation.e.apps.data.enums.User
import foundation.e.apps.data.login.core.AuthObject
import foundation.e.apps.data.login.core.StoreAuthResult
import foundation.e.apps.data.login.core.StoreAuthenticator
import foundation.e.apps.data.login.core.StoreType
import foundation.e.apps.data.preference.AppLoungeDataStore
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.Json
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config

@RunWith(RobolectricTestRunner::class)
@Config(sdk = [30])
class AuthenticatorRepositoryTest {

    @Test
    fun getGPlayAuthOrThrow_returnsStoredAuth() = runTest {
        val authData = AuthData(email = "user@example.com")
        val appLoungeDataStore = createDataStore()
        appLoungeDataStore.saveAuthData(authData)
        val repository = AuthenticatorRepository(emptyList(), appLoungeDataStore)

        val result = repository.getGPlayAuthOrThrow()

        assertThat(result).isEqualTo(authData)
    }

    @Test
    fun fetchAuthObjects_logsOutAndPersistsAuthData() = runTest {
        val authData = AuthData(email = "user@example.com")
        val authObject = AuthObject.GPlayAuth(ResultSupreme.Success(authData), User.GOOGLE)
        val storeResult = StoreAuthResult(authObject, authData)
        val appLoungeDataStore = createDataStore()
        val playAuthenticator = mockk<StoreAuthenticator>()
        val inactiveAuthenticator = mockk<StoreAuthenticator>()

        every { playAuthenticator.storeType } returns StoreType.PLAY_STORE
        every { inactiveAuthenticator.storeType } returns StoreType.CLEAN_APK
        every { playAuthenticator.isStoreActive() } returns true
        every { inactiveAuthenticator.isStoreActive() } returns false
        coEvery { playAuthenticator.logout() } returns Unit
        coEvery { playAuthenticator.login() } returns storeResult
        val repository = AuthenticatorRepository(listOf(playAuthenticator, inactiveAuthenticator), appLoungeDataStore)

        val result = repository.fetchAuthObjects(listOf(StoreType.PLAY_STORE))

        assertThat(result).containsExactly(authObject)
        coVerify { playAuthenticator.logout() }
        assertThat(appLoungeDataStore.getAuthData()).isEqualTo(authData)
    }

    @Test
    fun getValidatedAuthData_returnsErrorWhenMissingPlayStoreAuthenticator() = runTest {
        val appLoungeDataStore = createDataStore()
        val cleanApkAuthenticator = mockk<StoreAuthenticator>()
        every { cleanApkAuthenticator.storeType } returns StoreType.CLEAN_APK
        val repository = AuthenticatorRepository(listOf(cleanApkAuthenticator), appLoungeDataStore)

        val result = repository.getValidatedAuthData()

        assertThat(result).isInstanceOf(ResultSupreme.Error::class.java)
    }

    @Test
    fun getValidatedAuthData_logsOutAndPersistsAuthData() = runTest {
        val authData = AuthData(email = "user@example.com")
        val authObject = AuthObject.GPlayAuth(ResultSupreme.Success(authData), User.GOOGLE)
        val storeResult = StoreAuthResult(authObject, authData)
        val appLoungeDataStore = createDataStore()
        val playAuthenticator = mockk<StoreAuthenticator>()

        every { playAuthenticator.storeType } returns StoreType.PLAY_STORE
        coEvery { playAuthenticator.logout() } returns Unit
        coEvery { playAuthenticator.login() } returns storeResult

        val repository = AuthenticatorRepository(listOf(playAuthenticator), appLoungeDataStore)

        val result = repository.getValidatedAuthData()

        assertThat(result).isInstanceOf(ResultSupreme.Success::class.java)
        coVerify { playAuthenticator.logout() }
        assertThat(appLoungeDataStore.getAuthData()).isEqualTo(authData)
    }

    private fun createDataStore(): AppLoungeDataStore {
        val context = ApplicationProvider.getApplicationContext<Context>()
        val json = Json { ignoreUnknownKeys = true }
        return AppLoungeDataStore(context, json)
    }
}
+149 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2026 e Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package foundation.e.apps.install.updates

import android.app.NotificationManager
import android.content.Context
import android.content.SharedPreferences
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.os.Build
import androidx.work.Data
import androidx.work.WorkerParameters
import com.aurora.gplayapi.data.models.AuthData
import com.google.common.truth.Truth.assertThat
import foundation.e.apps.data.ResultSupreme
import foundation.e.apps.data.application.data.Application
import foundation.e.apps.data.blockedApps.BlockedAppRepository
import foundation.e.apps.data.enums.ResultStatus
import foundation.e.apps.data.enums.User
import foundation.e.apps.data.gitlab.SystemAppsUpdatesRepository
import foundation.e.apps.data.login.core.AuthObject
import foundation.e.apps.data.login.core.StoreAuthResult
import foundation.e.apps.data.login.core.StoreAuthenticator
import foundation.e.apps.data.login.core.StoreType
import foundation.e.apps.data.login.repository.AuthenticatorRepository
import foundation.e.apps.data.login.state.LoginState
import foundation.e.apps.data.preference.AppLoungeDataStore
import foundation.e.apps.data.updates.UpdatesManagerRepository
import foundation.e.apps.install.workmanager.AppInstallProcessor
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config

@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.N])
class UpdatesWorkerTest {

    @Test
    fun doWork_retriesUpdatesAfterAuthRefresh() = runTest {
        val dataStoreContext = RuntimeEnvironment.getApplication()
        val workerContext = mock<Context>()
        val sharedPreferences = mock<SharedPreferences>()
        val connectivityManager = mock<ConnectivityManager>()
        val network = mock<Network>()
        val networkCapabilities = mock<NetworkCapabilities>()
        val notificationManager = mock<NotificationManager>()
        val params = mock<WorkerParameters>()
        val updatesManagerRepository = mock<UpdatesManagerRepository>()
        val appLoungeDataStore = createDataStore(dataStoreContext)
        val storeAuthenticator = mockk<StoreAuthenticator>()
        val authenticatorRepository = AuthenticatorRepository(listOf(storeAuthenticator), appLoungeDataStore)
        val appInstallProcessor = mock<AppInstallProcessor>()
        val blockedAppRepository = mock<BlockedAppRepository>()
        val systemAppsUpdatesRepository = mock<SystemAppsUpdatesRepository>()
        val authData = AuthData(email = "user@example.com")
        val applications = listOf<Application>()

        val inputData = Data.Builder()
            .putBoolean(UpdatesWorker.IS_AUTO_UPDATE, false)
            .build()

        whenever(workerContext.applicationContext).thenReturn(workerContext)
        whenever(workerContext.getSharedPreferences(any(), any())).thenReturn(sharedPreferences)
        whenever(workerContext.getString(any())).thenReturn("key")
        whenever(workerContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(connectivityManager)
        whenever(workerContext.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(notificationManager)
        whenever(workerContext.checkSelfPermission(any())).thenReturn(android.content.pm.PackageManager.PERMISSION_GRANTED)
        whenever(connectivityManager.activeNetwork).thenReturn(network)
        whenever(connectivityManager.getNetworkCapabilities(network)).thenReturn(networkCapabilities)
        whenever(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)).thenReturn(true)
        whenever(sharedPreferences.getBoolean(any(), any())).thenReturn(true)

        appLoungeDataStore.destroyCredentials()
        appLoungeDataStore.saveUserType(User.GOOGLE)
        appLoungeDataStore.saveAuthData(authData)

        val user = appLoungeDataStore.getUser()
        val loginState = appLoungeDataStore.getLoginState()

        assertThat(user).isEqualTo(User.GOOGLE)
        assertThat(loginState).isEqualTo(LoginState.AVAILABLE)

        every { storeAuthenticator.storeType } returns StoreType.PLAY_STORE
        every { storeAuthenticator.isStoreActive() } returns true
        coEvery { storeAuthenticator.logout() } returns Unit
        coEvery { storeAuthenticator.login() } returns StoreAuthResult(
            AuthObject.GPlayAuth(ResultSupreme.Success(authData), User.GOOGLE),
            authData
        )

        whenever(params.inputData).thenReturn(inputData)
        whenever(updatesManagerRepository.getUpdates()).thenReturn(
            Pair(applications, ResultStatus.RETRY),
            Pair(applications, ResultStatus.OK)
        )

        whenever(updatesManagerRepository.getUpdatesOSS()).thenReturn(Pair(applications, ResultStatus.OK))
        whenever(systemAppsUpdatesRepository.fetchUpdatableSystemApps(true)).thenReturn(Unit)

        val worker = UpdatesWorker(
            workerContext,
            params,
            updatesManagerRepository,
            appLoungeDataStore,
            authenticatorRepository,
            appInstallProcessor,
            blockedAppRepository,
            systemAppsUpdatesRepository
        )

        worker.doWork()
        verify(updatesManagerRepository, times(2)).getUpdates()
        coVerify { storeAuthenticator.login() }
    }

    private fun createDataStore(context: Context): AppLoungeDataStore {
        val json = kotlinx.serialization.json.Json { ignoreUnknownKeys = true }
        return AppLoungeDataStore(context, json)
    }
}