fix: Only suggest upgrading to a version F-Droid has built (#717)
The F-Droid API can return a `suggestedVersionCode` that F-Droid has not successfully built (e.g., there was a network issue preventing F-Droid from fetching the source code at the time of the last build). This meant users were being prompted to update when there was not a built package to update to. Fix this by verifying that `suggestedVersionCode` appears in the list of packages. If it doesn't then fall back to the highest version code in the list of packages. Fixes #684
This commit is contained in:
parent
de7e5a9df9
commit
61afde882c
|
@ -34,6 +34,19 @@ class UpdateCheck @Inject constructor(
|
|||
}
|
||||
|
||||
override suspend fun remoteFetchLatestVersionCode(): Int? {
|
||||
return fdroidService.getPackage(BuildConfig.APPLICATION_ID).getOrNull()?.suggestedVersionCode
|
||||
val fdroidPackage = fdroidService.getPackage(BuildConfig.APPLICATION_ID).getOrNull() ?: return null
|
||||
|
||||
// `packages` is a list of all packages that have been built and are available.
|
||||
//
|
||||
// The package with `suggestedVersionCode` might not have been built yet (see
|
||||
// https://github.com/pachli/pachli-android/issues/684).
|
||||
//
|
||||
// Check that `suggestedVersionCode` appears in the list of packages. If it
|
||||
// does, use that.
|
||||
val suggestedVersionCode = fdroidPackage.suggestedVersionCode
|
||||
if (fdroidPackage.packages.any { it.versionCode == suggestedVersionCode }) return suggestedVersionCode
|
||||
|
||||
// Otherwise, use the highest version code in `packages`.
|
||||
return fdroidPackage.packages.maxByOrNull { it.versionCode }?.versionCode
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright 2024 Pachli Association
|
||||
*
|
||||
* This file is a part of Pachli.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Pachli 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 Pachli; if not,
|
||||
* see <http://www.gnu.org/licenses>.
|
||||
*/
|
||||
|
||||
package app.pachli.updatecheck
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import app.pachli.core.preferences.SharedPreferencesRepository
|
||||
import app.pachli.core.testing.fakes.InMemorySharedPreferences
|
||||
import at.connyduck.calladapter.networkresult.NetworkResult
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.reset
|
||||
import org.mockito.kotlin.stub
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class UpdateCheckTest {
|
||||
private val fdroidService: FdroidService = mock()
|
||||
private lateinit var updateCheck: UpdateCheck
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
reset(fdroidService)
|
||||
updateCheck = UpdateCheck(
|
||||
SharedPreferencesRepository(InMemorySharedPreferences(), TestScope()),
|
||||
fdroidService,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `remoteFetchLatestVersionCode returns null on network error`() = runTest {
|
||||
fdroidService.stub {
|
||||
onBlocking { getPackage(any()) } doReturn NetworkResult.failure(Exception())
|
||||
}
|
||||
|
||||
assertThat(updateCheck.remoteFetchLatestVersionCode()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `remoteFetchLatestVersionCode returns suggestedVersionCode if in packages`() = runTest {
|
||||
fdroidService.stub {
|
||||
onBlocking { getPackage(any()) } doReturn NetworkResult.success(
|
||||
FdroidPackage(
|
||||
packageName = "app.pachli",
|
||||
suggestedVersionCode = 3,
|
||||
packages = listOf(
|
||||
FdroidPackageVersion(versionName = "3.0", versionCode = 3),
|
||||
FdroidPackageVersion(versionName = "2.0", versionCode = 2),
|
||||
FdroidPackageVersion(versionName = "1.0", versionCode = 1),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// "3" is the `suggestedVersionCode`, and is in `packages`, so should be returned.
|
||||
assertThat(updateCheck.remoteFetchLatestVersionCode()).isEqualTo(3)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `remoteFetchLatestVersionCode returns greatest code if suggestedVersionCode is missing`() = runTest {
|
||||
fdroidService.stub {
|
||||
onBlocking { getPackage(any()) } doReturn NetworkResult.success(
|
||||
FdroidPackage(
|
||||
packageName = "app.pachli",
|
||||
suggestedVersionCode = 3,
|
||||
packages = listOf(
|
||||
FdroidPackageVersion(versionName = "2.0", versionCode = 2),
|
||||
FdroidPackageVersion(versionName = "1.0", versionCode = 1),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// "3" is the `suggestedVersionCode`, but is not in `packages`, so the greatest
|
||||
// `versionCode` in `packages` should be returned.
|
||||
assertThat(updateCheck.remoteFetchLatestVersionCode()).isEqualTo(2)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue