mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-11 13:11:01 +00:00
For #13507 - Adds tests for ReviewPromptController
This commit is contained in:
parent
56b730f0e8
commit
c6687d976e
@ -7,6 +7,8 @@
|
|||||||
<!-- The Sentry SDK is compiled against parts of the Java SDK that are not available in the Android SDK.
|
<!-- The Sentry SDK is compiled against parts of the Java SDK that are not available in the Android SDK.
|
||||||
Let's just ignore issues in the Sentry code since that is a third-party dependency anyways. -->
|
Let's just ignore issues in the Sentry code since that is a third-party dependency anyways. -->
|
||||||
<ignore path="**/sentry*.jar" />
|
<ignore path="**/sentry*.jar" />
|
||||||
|
<!-- Temporary until https://github.com/Kotlin/kotlinx.coroutines/issues/2004 is resolved. -->
|
||||||
|
<ignore path="**/kotlinx-coroutines-core-*.jar"/>
|
||||||
</issue>
|
</issue>
|
||||||
<!-- Lints that don't apply to our translation process -->
|
<!-- Lints that don't apply to our translation process -->
|
||||||
<issue id="MissingTranslation" severity="ignore" />
|
<issue id="MissingTranslation" severity="ignore" />
|
||||||
|
@ -26,7 +26,7 @@ interface ReviewSettings {
|
|||||||
*/
|
*/
|
||||||
class FenixReviewSettings(
|
class FenixReviewSettings(
|
||||||
val settings: Settings
|
val settings: Settings
|
||||||
): ReviewSettings {
|
) : ReviewSettings {
|
||||||
override var numberOfAppLaunches: Int
|
override var numberOfAppLaunches: Int
|
||||||
get() = settings.numberOfAppLaunches
|
get() = settings.numberOfAppLaunches
|
||||||
set(value) { settings.numberOfAppLaunches = value }
|
set(value) { settings.numberOfAppLaunches = value }
|
||||||
@ -43,14 +43,16 @@ class FenixReviewSettings(
|
|||||||
class ReviewPromptController(
|
class ReviewPromptController(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val reviewSettings: ReviewSettings,
|
private val reviewSettings: ReviewSettings,
|
||||||
private val timeNowInMillis: () -> Long = { System.currentTimeMillis() }
|
private val timeNowInMillis: () -> Long = { System.currentTimeMillis() },
|
||||||
|
private val tryPromptReview: suspend (Activity) -> Unit = {
|
||||||
|
val manager = ReviewManagerFactory.create(context)
|
||||||
|
val reviewInfo = manager.requestReview()
|
||||||
|
manager.launchReview(it, reviewInfo)
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
suspend fun promptReview(activity: Activity) {
|
suspend fun promptReview(activity: Activity) {
|
||||||
if (shouldShowPrompt()) {
|
if (shouldShowPrompt()) {
|
||||||
val manager = ReviewManagerFactory.create(context)
|
tryPromptReview(activity)
|
||||||
val reviewInfo = manager.requestReview()
|
|
||||||
manager.launchReview(activity, reviewInfo)
|
|
||||||
|
|
||||||
reviewSettings.lastReviewPromptTimeInMillis = timeNowInMillis()
|
reviewSettings.lastReviewPromptTimeInMillis = timeNowInMillis()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,14 +65,18 @@ class ReviewPromptController(
|
|||||||
fun shouldShowPrompt(): Boolean {
|
fun shouldShowPrompt(): Boolean {
|
||||||
if (!reviewSettings.isDefaultBrowser) { return false }
|
if (!reviewSettings.isDefaultBrowser) { return false }
|
||||||
|
|
||||||
val hasOpenedFiveTimes = reviewSettings.numberOfAppLaunches >= 5
|
val hasOpenedFiveTimes = reviewSettings.numberOfAppLaunches >= NUMBER_OF_LAUNCHES_REQUIRED
|
||||||
val apprxFourMonthsAgo = timeNowInMillis() - (APPRX_MONTH_IN_MILLIS * 4)
|
val now = timeNowInMillis()
|
||||||
val hasNotBeenPromptedLastFourMonths = reviewSettings.lastReviewPromptTimeInMillis <= apprxFourMonthsAgo
|
val apprxFourMonthsAgo = now - (APPRX_MONTH_IN_MILLIS * NUMBER_OF_MONTHS_TO_PASS)
|
||||||
|
val lastPrompt = reviewSettings.lastReviewPromptTimeInMillis
|
||||||
|
val hasNotBeenPromptedLastFourMonths = lastPrompt == 0L || lastPrompt <= apprxFourMonthsAgo
|
||||||
|
|
||||||
return hasOpenedFiveTimes && hasNotBeenPromptedLastFourMonths
|
return hasOpenedFiveTimes && hasNotBeenPromptedLastFourMonths
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val APPRX_MONTH_IN_MILLIS: Long = 1000L * 60L * 60L * 24L * 30L
|
private const val APPRX_MONTH_IN_MILLIS: Long = 1000L * 60L * 60L * 24L * 30L
|
||||||
|
private const val NUMBER_OF_LAUNCHES_REQUIRED = 5
|
||||||
|
private const val NUMBER_OF_MONTHS_TO_PASS = 4
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -42,9 +42,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE
|
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.play.core.ktx.launchReview
|
|
||||||
import com.google.android.play.core.ktx.requestReview
|
|
||||||
import com.google.android.play.core.review.ReviewManagerFactory
|
|
||||||
import kotlinx.android.synthetic.main.fragment_home.*
|
import kotlinx.android.synthetic.main.fragment_home.*
|
||||||
import kotlinx.android.synthetic.main.fragment_home.view.*
|
import kotlinx.android.synthetic.main.fragment_home.view.*
|
||||||
import kotlinx.android.synthetic.main.no_collections_message.view.*
|
import kotlinx.android.synthetic.main.no_collections_message.view.*
|
||||||
|
@ -12,7 +12,6 @@ import android.content.SharedPreferences
|
|||||||
import android.content.pm.ShortcutManager
|
import android.content.pm.ShortcutManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.view.accessibility.AccessibilityManager
|
import android.view.accessibility.AccessibilityManager
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.annotation.VisibleForTesting.PRIVATE
|
import androidx.annotation.VisibleForTesting.PRIVATE
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
@ -40,7 +39,6 @@ import org.mozilla.fenix.settings.logins.SavedLoginsSortingStrategyMenu
|
|||||||
import org.mozilla.fenix.settings.logins.SortingStrategy
|
import org.mozilla.fenix.settings.logins.SortingStrategy
|
||||||
import org.mozilla.fenix.settings.registerOnSharedPreferenceChangeListener
|
import org.mozilla.fenix.settings.registerOnSharedPreferenceChangeListener
|
||||||
import java.security.InvalidParameterException
|
import java.security.InvalidParameterException
|
||||||
import java.time.LocalDate
|
|
||||||
|
|
||||||
private const val AUTOPLAY_USER_SETTING = "AUTOPLAY_USER_SETTING"
|
private const val AUTOPLAY_USER_SETTING = "AUTOPLAY_USER_SETTING"
|
||||||
|
|
||||||
|
@ -0,0 +1,144 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
package org.mozilla.fenix.components
|
||||||
|
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.runBlockingTest
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.HomeActivity
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
|
||||||
|
class TestReviewSettings(
|
||||||
|
override var numberOfAppLaunches: Int = 0,
|
||||||
|
var isDefault: Boolean = false,
|
||||||
|
override var lastReviewPromptTimeInMillis: Long = 0
|
||||||
|
) : ReviewSettings {
|
||||||
|
override val isDefaultBrowser: Boolean
|
||||||
|
get() = isDefault
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExperimentalCoroutinesApi
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class ReviewPromptControllerTest {
|
||||||
|
@Test
|
||||||
|
fun promptReviewDoesNotSetMillis() = runBlockingTest {
|
||||||
|
var promptWasCalled = false
|
||||||
|
val settings = TestReviewSettings(
|
||||||
|
numberOfAppLaunches = 5,
|
||||||
|
isDefault = false,
|
||||||
|
lastReviewPromptTimeInMillis = 0L
|
||||||
|
)
|
||||||
|
|
||||||
|
val controller = ReviewPromptController(
|
||||||
|
testContext,
|
||||||
|
settings,
|
||||||
|
{ 100L },
|
||||||
|
{ promptWasCalled = true }
|
||||||
|
)
|
||||||
|
|
||||||
|
controller.promptReview(HomeActivity())
|
||||||
|
assertEquals(settings.lastReviewPromptTimeInMillis, 0L)
|
||||||
|
assertFalse(promptWasCalled)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun promptReviewSetsMillisIfSuccessful() = runBlockingTest {
|
||||||
|
var promptWasCalled = false
|
||||||
|
val settings = TestReviewSettings(
|
||||||
|
numberOfAppLaunches = 5,
|
||||||
|
isDefault = true,
|
||||||
|
lastReviewPromptTimeInMillis = 0L
|
||||||
|
)
|
||||||
|
|
||||||
|
val controller = ReviewPromptController(
|
||||||
|
testContext,
|
||||||
|
settings,
|
||||||
|
{ 100L },
|
||||||
|
{ promptWasCalled = true }
|
||||||
|
)
|
||||||
|
|
||||||
|
controller.promptReview(HomeActivity())
|
||||||
|
assertEquals(100L, settings.lastReviewPromptTimeInMillis)
|
||||||
|
assertTrue(promptWasCalled)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun trackApplicationLaunch() {
|
||||||
|
val settings = TestReviewSettings(
|
||||||
|
numberOfAppLaunches = 4,
|
||||||
|
isDefault = true,
|
||||||
|
lastReviewPromptTimeInMillis = 0L
|
||||||
|
)
|
||||||
|
|
||||||
|
val controller = ReviewPromptController(
|
||||||
|
testContext,
|
||||||
|
settings,
|
||||||
|
{ 100L }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(4, settings.numberOfAppLaunches)
|
||||||
|
controller.trackApplicationLaunch()
|
||||||
|
assertEquals(5, settings.numberOfAppLaunches)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldShowPrompt() {
|
||||||
|
val settings = TestReviewSettings(
|
||||||
|
numberOfAppLaunches = 5,
|
||||||
|
isDefault = true,
|
||||||
|
lastReviewPromptTimeInMillis = 0L
|
||||||
|
)
|
||||||
|
|
||||||
|
val controller = ReviewPromptController(
|
||||||
|
testContext,
|
||||||
|
settings,
|
||||||
|
{ 1598416882805L }
|
||||||
|
)
|
||||||
|
|
||||||
|
// Test first success criteria
|
||||||
|
assertTrue(controller.shouldShowPrompt())
|
||||||
|
|
||||||
|
// Test with last prompt approx 4 months earlier
|
||||||
|
settings.apply {
|
||||||
|
numberOfAppLaunches = 5
|
||||||
|
isDefault = true
|
||||||
|
lastReviewPromptTimeInMillis = 1588048882804L
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(controller.shouldShowPrompt())
|
||||||
|
|
||||||
|
// Test without being the default browser
|
||||||
|
settings.apply {
|
||||||
|
numberOfAppLaunches = 5
|
||||||
|
isDefault = false
|
||||||
|
lastReviewPromptTimeInMillis = 1595824882805L
|
||||||
|
}
|
||||||
|
|
||||||
|
assertFalse(controller.shouldShowPrompt())
|
||||||
|
|
||||||
|
// Test with number of app launches < 5
|
||||||
|
settings.apply {
|
||||||
|
numberOfAppLaunches = 4
|
||||||
|
isDefault = true
|
||||||
|
lastReviewPromptTimeInMillis = 0L
|
||||||
|
}
|
||||||
|
|
||||||
|
assertFalse(controller.shouldShowPrompt())
|
||||||
|
|
||||||
|
// Test with last prompt less than 4 months ago
|
||||||
|
settings.apply {
|
||||||
|
numberOfAppLaunches = 5
|
||||||
|
isDefault = true
|
||||||
|
lastReviewPromptTimeInMillis = 1595824882905L
|
||||||
|
}
|
||||||
|
|
||||||
|
assertFalse(controller.shouldShowPrompt())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user