Skip to content

Commit

Permalink
Merge pull request #17536 from wordpress-mobile/task/check-wordpress-…
Browse files Browse the repository at this point in the history
…version-compatibility

[JP Content Migration Flow] Check Wordpress version compatibility
  • Loading branch information
Antonis Lilis authored Nov 25, 2022
2 parents 296b8fe + 6dd4699 commit 5154971
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import org.wordpress.android.ui.ActivityLauncher
import org.wordpress.android.ui.prefs.AppPrefsWrapper
import org.wordpress.android.util.BuildConfigWrapper
import org.wordpress.android.util.config.JetpackMigrationFlowFeatureConfig
import org.wordpress.android.util.helpers.Version
import org.wordpress.android.util.publicdata.AppStatus
import org.wordpress.android.util.publicdata.WordPressPublicData
import org.wordpress.android.viewmodel.ContextProvider
import javax.inject.Inject

Expand All @@ -14,13 +17,26 @@ class JetpackAppMigrationFlowUtils @Inject constructor(
private val contextProvider: ContextProvider,
private val appPrefsWrapper: AppPrefsWrapper,
private val accountStore: AccountStore,
private val appStatus: AppStatus,
private val wordPressPublicData: WordPressPublicData,
) {
private val minimumSupportedVersion = "21.3" // non semantic minimum supported version

fun shouldShowMigrationFlow() = buildConfigWrapper.isJetpackApp
&& jetpackMigrationFlowFeatureConfig.isEnabled()
&& appPrefsWrapper.getIsFirstTrySharedLoginJetpack()
&& !accountStore.hasAccessToken()
&& isWordPressInstalled()
&& isWordPressCompatible()

fun startJetpackMigrationFlow() {
ActivityLauncher.startJetpackMigrationFlow(contextProvider.getContext())
}

private fun isWordPressInstalled() = appStatus.isAppInstalled(wordPressPublicData.currentPackageId())

private fun isWordPressCompatible(): Boolean {
val wordPressVersion = wordPressPublicData.nonSemanticPackageVersion()
return wordPressVersion != null && Version(wordPressVersion) >= Version(minimumSupportedVersion)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import org.wordpress.android.util.publicdata.WordPressPublicData.PackageName.Van
import org.wordpress.android.util.publicdata.WordPressPublicData.PackageName.Wasabi
import javax.inject.Inject

class WordPressPublicData @Inject constructor() {
class WordPressPublicData @Inject constructor(private val packageManagerWrapper: PackageManagerWrapper) {
private sealed class PackageName(val type: String, val value: String) {
object Jalapeno : PackageName("jalapeno", "org.wordpress.android.prealpha")

Expand All @@ -21,4 +21,20 @@ class WordPressPublicData @Inject constructor() {
Wasabi.type -> Wasabi.value
else -> throw IllegalArgumentException("Failed to get Jetpack package ID: build flavor not found.")
}

fun currentPackageVersion(): String? = packageManagerWrapper.getPackageInfo(currentPackageId())?.versionName

fun nonSemanticPackageVersion(): String? {
val rawVersion = currentPackageVersion() ?: return null

// Clean app semantic versioning and keep ony major-minor version info. E.g 21.2-rc-3 turns to 21.2
val majorMinorRegex = "^(\\d*)(\\.(\\d*))".toRegex()
val wordPressVersion = majorMinorRegex.find(rawVersion)?.value

// Verify that the resulting version is supported by org.wordpress.android.util.helpers.Version.Version
val versionIsSupportedForComparison = wordPressVersion !=null
&& Regex("[0-9]+(\\.[0-9]+)*").matchEntire(wordPressVersion) != null

return if (versionIsSupportedForComparison) wordPressVersion else null
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,92 @@
package org.wordpress.android.sharedlogin

import android.content.pm.PackageInfo
import org.assertj.core.api.Assertions
import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import org.wordpress.android.util.publicdata.PackageManagerWrapper
import org.wordpress.android.util.publicdata.WordPressPublicData

class WordPressPublicDataTest {
private val classToTest = WordPressPublicData()
private val packageManagerWrapper: PackageManagerWrapper = mock()

private val classToTest = WordPressPublicData(packageManagerWrapper)

@Test
fun `Should return correct current package ID`() {
val actual = classToTest.currentPackageId()
val expected = "org.wordpress.android"
Assertions.assertThat(actual).isEqualTo(expected)
}

@Test
fun `Should return correct current package version`() {
mockVersion("21.2-rc-3")
val actual = classToTest.currentPackageVersion()
val expected = "21.2-rc-3"
Assertions.assertThat(actual).isEqualTo(expected)
}

@Test
fun `Versions without semantic information should be equal to the non semantic version`() {
mockVersion("21.2")
val actual = classToTest.nonSemanticPackageVersion()
val expected = "21.2"
Assertions.assertThat(actual).isEqualTo(expected)
}

@Test
fun `Release candidate versions should be stripped from the non semantic version`() {
mockVersion("21.2-rc-3")
val actual = classToTest.nonSemanticPackageVersion()
val expected = "21.2"
Assertions.assertThat(actual).isEqualTo(expected)
}

@Test
fun `Alpha versions should be stripped from the non semantic version`() {
mockVersion("21.2-alpha-3")
val actual = classToTest.nonSemanticPackageVersion()
val expected = "21.2"
Assertions.assertThat(actual).isEqualTo(expected)
}

@Test
fun `Invalid versions should return a null non semantic version`() {
mockVersion("21.a2...-rc2")
val actual = classToTest.nonSemanticPackageVersion()
val expected = null
Assertions.assertThat(actual).isEqualTo(expected)
}

@Test
fun `Empty versions should return a null non semantic version`() {
mockVersion("")
val actual = classToTest.nonSemanticPackageVersion()
val expected = null
Assertions.assertThat(actual).isEqualTo(expected)
}

@Test
fun `Only the major-minor version information is returned`() {
mockVersion("21.3.1")
val actual = classToTest.nonSemanticPackageVersion()
val expected = "21.3"
Assertions.assertThat(actual).isEqualTo(expected)
}

@Test
fun `When only the major is provided a null non semantic version is returned`() {
mockVersion("21")
val actual = classToTest.nonSemanticPackageVersion()
val expected = null
Assertions.assertThat(actual).isEqualTo(expected)
}

private fun mockVersion(version: String) {
val packageInfo = PackageInfo().apply { versionName = version }
whenever(packageManagerWrapper.getPackageInfo(any(), any())).thenReturn(packageInfo)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package org.wordpress.android.ui.utils

import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnitRunner
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import org.wordpress.android.fluxc.store.AccountStore
import org.wordpress.android.ui.prefs.AppPrefsWrapper
import org.wordpress.android.util.BuildConfigWrapper
import org.wordpress.android.util.config.JetpackMigrationFlowFeatureConfig
import org.wordpress.android.util.publicdata.AppStatus
import org.wordpress.android.util.publicdata.WordPressPublicData
import org.wordpress.android.viewmodel.ContextProvider

@RunWith(MockitoJUnitRunner::class)
class JetpackAppMigrationFlowUtilsTest {
private val buildConfigWrapper: BuildConfigWrapper = mock()
private val jetpackMigrationFlowFeatureConfig: JetpackMigrationFlowFeatureConfig = mock()
private val contextProvider: ContextProvider = mock()
private val appPrefsWrapper: AppPrefsWrapper = mock()
private val accountStore: AccountStore = mock()
private val appStatus: AppStatus = mock()
private val wordPressPublicData: WordPressPublicData = mock()

private val jetpackAppMigrationFlowUtils = JetpackAppMigrationFlowUtils(
buildConfigWrapper,
jetpackMigrationFlowFeatureConfig,
contextProvider,
appPrefsWrapper,
accountStore,
appStatus,
wordPressPublicData
)

@Before
fun setUp() {
whenever(buildConfigWrapper.isJetpackApp).thenReturn(true)
whenever(jetpackMigrationFlowFeatureConfig.isEnabled()).thenReturn(true)
whenever(appPrefsWrapper.getIsFirstTrySharedLoginJetpack()).thenReturn(true)
whenever(accountStore.hasAccessToken()).thenReturn(false)
whenever(wordPressPublicData.currentPackageId()).thenReturn("package")
whenever(appStatus.isAppInstalled(any())).thenReturn(true)
whenever(wordPressPublicData.nonSemanticPackageVersion()).thenReturn("21.3")
}

@Test
fun `When all conditions are met the migration flow should be shown`() {
val expected = true
val actual = jetpackAppMigrationFlowUtils.shouldShowMigrationFlow()
Assert.assertEquals(expected, actual)
}

@Test
fun `When not in the Jetpack app the migration flow should not be shown`() {
whenever(buildConfigWrapper.isJetpackApp).thenReturn(false)
val expected = false
val actual = jetpackAppMigrationFlowUtils.shouldShowMigrationFlow()
Assert.assertEquals(expected, actual)
}

@Test
fun `When the jetpackMigrationFlow is not enableed the Jetpack app the migration flow should not be shown`() {
whenever(jetpackMigrationFlowFeatureConfig.isEnabled()).thenReturn(false)
val expected = false
val actual = jetpackAppMigrationFlowUtils.shouldShowMigrationFlow()
Assert.assertEquals(expected, actual)
}

@Test
fun `When the it is not the first migration attempt the Jetpack app the migration flow should not be shown`() {
whenever(appPrefsWrapper.getIsFirstTrySharedLoginJetpack()).thenReturn(false)
val expected = false
val actual = jetpackAppMigrationFlowUtils.shouldShowMigrationFlow()
Assert.assertEquals(expected, actual)
}

@Test
fun `If the user is logged in the Jetpack app the migration flow should not be shown`() {
whenever(accountStore.hasAccessToken()).thenReturn(true)
val expected = false
val actual = jetpackAppMigrationFlowUtils.shouldShowMigrationFlow()
Assert.assertEquals(expected, actual)
}

@Test
fun `When the WordPress app is not installed the Jetpack app the migration flow should not be shown`() {
whenever(appStatus.isAppInstalled(any())).thenReturn(false)
val expected = false
val actual = jetpackAppMigrationFlowUtils.shouldShowMigrationFlow()
Assert.assertEquals(expected, actual)
}

@Test
fun `When the WordPress app is not compatible the Jetpack app the migration flow should not be shown`() {
whenever(wordPressPublicData.nonSemanticPackageVersion()).thenReturn("21.2")
val expected = false
val actual = jetpackAppMigrationFlowUtils.shouldShowMigrationFlow()
Assert.assertEquals(expected, actual)
}

@Test
fun `When the WordPress app version is null the Jetpack app the migration flow should not be shown`() {
whenever(wordPressPublicData.nonSemanticPackageVersion()).thenReturn(null)
val expected = false
val actual = jetpackAppMigrationFlowUtils.shouldShowMigrationFlow()
Assert.assertEquals(expected, actual)
}
}

0 comments on commit 5154971

Please sign in to comment.