diff --git a/app/src/main/java/foundation/e/apps/data/gplay/utils/GPlayHttpClient.kt b/app/src/main/java/foundation/e/apps/data/gplay/utils/GPlayHttpClient.kt
index acb44e965307d9bd3935c45e514cec46a8b363e1..2bfd5578aa5ff7dc8d8ef530a04dd50c0f1c7438 100644
--- a/app/src/main/java/foundation/e/apps/data/gplay/utils/GPlayHttpClient.kt
+++ b/app/src/main/java/foundation/e/apps/data/gplay/utils/GPlayHttpClient.kt
@@ -19,6 +19,7 @@
package foundation.e.apps.data.gplay.utils
+import androidx.annotation.VisibleForTesting
import com.aurora.gplayapi.data.models.PlayResponse
import com.aurora.gplayapi.network.IHttpClient
import foundation.e.apps.data.login.AuthObject
@@ -61,7 +62,8 @@ class GPlayHttpClient @Inject constructor(
const val STATUS_CODE_TIMEOUT = 408
}
- private val okHttpClient = OkHttpClient().newBuilder()
+ @VisibleForTesting
+ var okHttpClient = OkHttpClient().newBuilder()
.retryOnConnectionFailure(false)
.callTimeout(HTTP_TIMEOUT_IN_SECOND, TimeUnit.SECONDS)
.followRedirects(true)
diff --git a/app/src/test/java/foundation/e/apps/FusedApiImplTest.kt b/app/src/test/java/foundation/e/apps/fused/FusedApiImplTest.kt
similarity index 99%
rename from app/src/test/java/foundation/e/apps/FusedApiImplTest.kt
rename to app/src/test/java/foundation/e/apps/fused/FusedApiImplTest.kt
index 3096c444c0309461cf941da1d3d1209197c0deb6..816394481bf93a1dbfd262897aec913cbe474d64 100644
--- a/app/src/test/java/foundation/e/apps/FusedApiImplTest.kt
+++ b/app/src/test/java/foundation/e/apps/fused/FusedApiImplTest.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package foundation.e.apps
+package foundation.e.apps.fused
import android.content.Context
import android.text.format.Formatter
@@ -25,6 +25,8 @@ import com.aurora.gplayapi.data.models.App
import com.aurora.gplayapi.data.models.AuthData
import com.aurora.gplayapi.data.models.Category
import com.aurora.gplayapi.data.models.SearchBundle
+import foundation.e.apps.FakePreferenceModule
+import foundation.e.apps.R
import foundation.e.apps.data.cleanapk.data.categories.Categories
import foundation.e.apps.data.cleanapk.data.search.Search
import foundation.e.apps.data.cleanapk.repositories.CleanApkRepository
@@ -682,7 +684,7 @@ class FusedApiImplTest {
Mockito.`when`(
gPlayAPIRepository.getCategories(CategoryType.APPLICATION)
- ).thenThrow(RuntimeException())
+ ).thenThrow()
val categoryListResponse =
fusedAPIImpl.getCategoriesList(CategoryType.APPLICATION)
diff --git a/app/src/test/java/foundation/e/apps/FusedApiRepositoryTest.kt b/app/src/test/java/foundation/e/apps/fused/FusedApiRepositoryTest.kt
similarity index 98%
rename from app/src/test/java/foundation/e/apps/FusedApiRepositoryTest.kt
rename to app/src/test/java/foundation/e/apps/fused/FusedApiRepositoryTest.kt
index 8e04ce98e89935f2a9afa77e22afd23f0523aab3..801ae4437c2ef778c07e7fd80d0c709c953040d8 100644
--- a/app/src/test/java/foundation/e/apps/FusedApiRepositoryTest.kt
+++ b/app/src/test/java/foundation/e/apps/fused/FusedApiRepositoryTest.kt
@@ -15,7 +15,7 @@
* along with this program. If not, see .
*/
-package foundation.e.apps
+package foundation.e.apps.fused
import foundation.e.apps.data.fused.FusedAPIRepository
import foundation.e.apps.data.fused.FusedApiImpl
diff --git a/app/src/test/java/foundation/e/apps/gplay/GplyHttpClientTest.kt b/app/src/test/java/foundation/e/apps/gplay/GplyHttpClientTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f906f6fb983e1c6d262a87fcf15dd520264da4b7
--- /dev/null
+++ b/app/src/test/java/foundation/e/apps/gplay/GplyHttpClientTest.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright MURENA SAS 2023
+ * Apps Quickly and easily install Android apps onto your device!
+ *
+ * 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 .
+ */
+
+package foundation.e.apps.gplay
+
+import com.aurora.gplayapi.data.models.PlayResponse
+import foundation.e.apps.data.gplay.utils.GPlayHttpClient
+import foundation.e.apps.data.login.AuthObject
+import foundation.e.apps.util.FakeCall
+import foundation.e.apps.util.MainCoroutineRule
+import foundation.e.apps.utils.SystemInfoProvider
+import foundation.e.apps.utils.eventBus.AppEvent
+import foundation.e.apps.utils.eventBus.EventBus
+import io.mockk.every
+import io.mockk.mockkObject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
+import okhttp3.Cache
+import okhttp3.OkHttpClient
+import okhttp3.RequestBody.Companion.toRequestBody
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.any
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+
+@OptIn(ExperimentalCoroutinesApi::class)
+class GplyHttpClientTest {
+
+ @Mock
+ private lateinit var cache: Cache
+
+ @Mock
+ private lateinit var okHttpClient: OkHttpClient
+
+ private lateinit var call: FakeCall
+
+ private lateinit var gPlayHttpClient: GPlayHttpClient
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @get:Rule
+ val coroutineTestRule = MainCoroutineRule()
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.openMocks(this)
+ gPlayHttpClient = GPlayHttpClient(cache)
+ gPlayHttpClient.okHttpClient = this.okHttpClient
+ call = FakeCall()
+ }
+
+ @Test
+ fun testPostWithMapFailedWhenStatus401() = runTest {
+ initMocks()
+ val response = gPlayHttpClient.post("http://abc.abc", mapOf(), mapOf())
+ assertResponse(response)
+ }
+
+ @Test
+ fun testPostWithRequestBodyFailedWhenStatus401() = runTest {
+ initMocks()
+ val response = gPlayHttpClient.post("http://abc.abc", mapOf(), "".toRequestBody())
+ assertResponse(response)
+ }
+
+ @Test
+ fun testPostWithByteArrayFailedWhenStatus401() = runTest {
+ initMocks()
+ val response = gPlayHttpClient.post("http://abc.abc", mapOf(), "".toByteArray())
+ assertResponse(response)
+ }
+
+ @Test
+ fun testGetWithoutParamsFailedWhenStatus401() = runTest {
+ initMocks()
+ val response = gPlayHttpClient.get(FakeCall.FAKE_URL, mapOf())
+ assertResponse(response)
+ }
+
+ @Test
+ fun testGetWithStringParamsFailedWhenStatus401() = runTest {
+ initMocks()
+ val response = gPlayHttpClient.get(FakeCall.FAKE_URL, mapOf(), "")
+ assertResponse(response)
+ }
+
+ @Test
+ fun testGetWithMapParamsFailedWhenStatus401() = runTest {
+ initMocks()
+ val response = gPlayHttpClient.get(FakeCall.FAKE_URL, mapOf(), mapOf())
+ assertResponse(response)
+ }
+
+ @Test
+ fun testPostAuthFailedWhenStatus401() = runTest {
+ initMocks()
+ val response = gPlayHttpClient.postAuth("http://abc.abc", "".toByteArray())
+ assertResponse(response)
+ }
+
+ private fun initMocks() {
+ call.willThrow401 = true
+ mockkObject(SystemInfoProvider)
+ every { SystemInfoProvider.getAppBuildInfo() } returns ""
+ Mockito.`when`(okHttpClient.newCall(any())).thenReturn(call)
+ }
+ private suspend fun assertResponse(response: PlayResponse) {
+ assertFalse(response.isSuccessful)
+ assertTrue(response.code == 401)
+ val event = EventBus.events.first()
+ assertTrue(event is AppEvent.InvalidAuthEvent)
+ assertTrue(event.data is String)
+ assertTrue(event.data == AuthObject.GPlayAuth::class.java.simpleName)
+ }
+}
diff --git a/app/src/test/java/foundation/e/apps/login/LoginViewModelTest.kt b/app/src/test/java/foundation/e/apps/login/LoginViewModelTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..01521a1fff76162299a3a1527e49cdab8f48db24
--- /dev/null
+++ b/app/src/test/java/foundation/e/apps/login/LoginViewModelTest.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright MURENA SAS 2023
+ * Apps Quickly and easily install Android apps onto your device!
+ *
+ * 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 .
+ */
+
+package foundation.e.apps.login
+
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
+import com.aurora.gplayapi.data.models.AuthData
+import foundation.e.apps.data.ResultSupreme
+import foundation.e.apps.data.enums.User
+import foundation.e.apps.data.login.AuthObject
+import foundation.e.apps.data.login.LoginSourceRepository
+import foundation.e.apps.data.login.LoginViewModel
+import okhttp3.Cache
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+class LoginViewModelTest {
+
+ @Mock
+ private lateinit var loginSourceRepository: LoginSourceRepository
+ @Mock
+ private lateinit var cache: Cache
+
+ private lateinit var loginViewModel: LoginViewModel
+
+ @Suppress("unused")
+ @get:Rule
+ val instantTaskExecutorRule: InstantTaskExecutorRule = InstantTaskExecutorRule()
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.openMocks(this)
+ loginViewModel = LoginViewModel(loginSourceRepository, cache)
+ }
+
+ @Test
+ fun testMarkInvalidAuthObject() {
+ val authObjectList = mutableListOf(
+ AuthObject.GPlayAuth(
+ ResultSupreme.Success(AuthData("aa@aa.com", "feri4234")), User.GOOGLE
+ )
+ )
+ loginViewModel.authObjects.value = authObjectList
+
+ loginViewModel.markInvalidAuthObject(AuthObject.GPlayAuth::class.java.simpleName)
+ val currentAuthObjectList = loginViewModel.authObjects.value as List
+ val invalidGplayAuth = currentAuthObjectList.find { it is AuthObject.GPlayAuth }
+
+ assert(invalidGplayAuth != null)
+ assert((invalidGplayAuth as AuthObject.GPlayAuth).result.isUnknownError())
+ }
+}
\ No newline at end of file
diff --git a/app/src/test/java/foundation/e/apps/util/FakeCall.kt b/app/src/test/java/foundation/e/apps/util/FakeCall.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1c6aa71d81dc64eb600d897a6eb7078b9f9ebc81
--- /dev/null
+++ b/app/src/test/java/foundation/e/apps/util/FakeCall.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright MURENA SAS 2023
+ * Apps Quickly and easily install Android apps onto your device!
+ *
+ * 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 .
+ */
+
+package foundation.e.apps.util
+
+import okhttp3.Call
+import okhttp3.Callback
+import okhttp3.Protocol
+import okhttp3.Request
+import okhttp3.Response
+import okhttp3.ResponseBody
+import okhttp3.ResponseBody.Companion.toResponseBody
+import okio.Timeout
+
+class FakeCall : Call {
+
+ var willThrow401 = false
+
+ companion object {
+ const val FAKE_URL = "https://abc.abc"
+ }
+
+ private val fakeRequest = Request.Builder().url(FAKE_URL).build()
+ override fun cancel() {
+ TODO("Not yet implemented")
+ }
+
+ override fun clone(): Call {
+ TODO("Not yet implemented")
+ }
+
+ override fun enqueue(responseCallback: Callback) {
+ TODO("Not yet implemented")
+ }
+
+ override fun execute(): Response {
+ if (willThrow401) {
+ return Response.Builder()
+ .request(fakeRequest)
+ .protocol(Protocol.HTTP_2)
+ .message("")
+ .code(401)
+ .body("".toResponseBody())
+ .build()
+ }
+ return Response.Builder().build()
+ }
+
+ override fun isCanceled(): Boolean {
+ TODO("Not yet implemented")
+ }
+
+ override fun isExecuted(): Boolean {
+ TODO("Not yet implemented")
+ }
+
+ override fun request(): Request {
+ TODO("Not yet implemented")
+ }
+
+ override fun timeout(): Timeout {
+ TODO("Not yet implemented")
+ }
+}
\ No newline at end of file