From 6d6b240e4845905194727c67a9ba88f44c89fde4 Mon Sep 17 00:00:00 2001 From: Denys M Date: Sat, 8 Jun 2019 22:12:44 +0300 Subject: [PATCH] Add unit tests for `Settings`. Add unit tests for `Settings`. --- app/build.gradle | 3 +- .../java/org/mozilla/fenix/utils/Settings.kt | 21 +- .../java/org/mozilla/fenix/ext/preferences.kt | 14 + .../org/mozilla/fenix/utils/SettingsTest.kt | 354 ++++++++++++++++++ buildSrc/src/main/java/Dependencies.kt | 3 + 5 files changed, 388 insertions(+), 7 deletions(-) create mode 100644 app/src/test/java/org/mozilla/fenix/ext/preferences.kt create mode 100644 app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt diff --git a/app/build.gradle b/app/build.gradle index 48a5fa8fa..105e1c331 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -394,7 +394,8 @@ dependencies { exclude group: 'com.android.support', module: 'support-annotations' } - testImplementation Deps.junit + testImplementation Deps.mozilla_support_test + testImplementation Deps.androidx_junit testImplementation Deps.robolectric implementation Deps.fragment_testing testImplementation Deps.places_forUnitTests diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index 96b5b9c34..e83b576a0 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -7,6 +7,8 @@ package org.mozilla.fenix.utils import android.content.Context import android.content.Context.MODE_PRIVATE import android.content.SharedPreferences +import androidx.annotation.VisibleForTesting +import androidx.annotation.VisibleForTesting.PRIVATE import mozilla.components.feature.sitepermissions.SitePermissionsRules import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.Config @@ -18,7 +20,10 @@ import java.security.InvalidParameterException * A simple wrapper for SharedPreferences that makes reading preference a little bit easier. */ @SuppressWarnings("TooManyFunctions") -class Settings private constructor(context: Context) { +class Settings private constructor( + context: Context, + private val isCrashReportEnabledInBuild: Boolean +) { companion object { const val autoBounceMaximumCount = 2 @@ -28,9 +33,12 @@ class Settings private constructor(context: Context) { @JvmStatic @Synchronized - fun getInstance(context: Context): Settings { + fun getInstance( + context: Context, + isCrashReportEnabledInBuild: Boolean = BuildConfig.CRASH_REPORTING && Config.channel.isReleased + ): Settings { if (instance == null) { - instance = Settings(context.applicationContext) + instance = Settings(context.applicationContext, isCrashReportEnabledInBuild) } return instance ?: throw AssertionError("Instance cleared") } @@ -52,8 +60,8 @@ class Settings private constructor(context: Context) { get() = preferences.getString(appContext.getPreferenceKey(R.string.pref_key_search_engine), "") ?: "" val isCrashReportingEnabled: Boolean - get() = preferences.getBoolean(appContext.getPreferenceKey(R.string.pref_key_crash_reporter), true) && - BuildConfig.CRASH_REPORTING && Config.channel.isReleased + get() = isCrashReportEnabledInBuild && + preferences.getBoolean(appContext.getPreferenceKey(R.string.pref_key_crash_reporter), true) val isRemoteDebuggingEnabled: Boolean get() = preferences.getBoolean(appContext.getPreferenceKey(R.string.pref_key_remote_debugging), false) @@ -152,7 +160,8 @@ class Settings private constructor(context: Context) { else -> appContext.getString(R.string.preference_light_theme) } - private val autoBounceQuickActionSheetCount: Int + @VisibleForTesting(otherwise = PRIVATE) + internal val autoBounceQuickActionSheetCount: Int get() = (preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_bounce_quick_action), 0)) fun incrementAutomaticBounceQuickActionSheetCount() { diff --git a/app/src/test/java/org/mozilla/fenix/ext/preferences.kt b/app/src/test/java/org/mozilla/fenix/ext/preferences.kt new file mode 100644 index 000000000..36a483554 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/ext/preferences.kt @@ -0,0 +1,14 @@ +/* + 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.ext + +import android.content.SharedPreferences + +/** + * Clear everything in shared preferences and commit changes immediately. + */ +fun SharedPreferences.clearAndCommit() = this.edit().clear().commit() \ No newline at end of file diff --git a/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt b/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt new file mode 100644 index 000000000..12f43b6ec --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt @@ -0,0 +1,354 @@ +/* + 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.utils + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import mozilla.components.feature.sitepermissions.SitePermissionsRules +import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ASK_TO_ALLOW +import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.BLOCKED +import mozilla.components.support.test.robolectric.testContext +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.TestApplication +import org.mozilla.fenix.ext.clearAndCommit +import org.robolectric.annotation.Config + +@RunWith(AndroidJUnit4::class) +@Config(application = TestApplication::class) +class SettingsTest { + + lateinit var settings: Settings + + @Before + fun setUp() { + settings = Settings.getInstance(testContext) + .apply(Settings::clear) + } + + @Test + fun usePrivateMode() { + // When just created + // Then + assertFalse(settings.usePrivateMode) + + // When + settings.setPrivateMode(true) + + // Then + assertTrue(settings.usePrivateMode) + + // When + settings.setPrivateMode(false) + + // Then + assertFalse(settings.usePrivateMode) + } + + @Test + fun defaultSearchEngineName() { + // When just created + // Then + assertEquals("", settings.defaultSearchEngineName) + + // When + settings.setDefaultSearchEngineByName("Mozilla") + + // Then + assertEquals("Mozilla", settings.defaultSearchEngineName) + } + + @Test + fun isCrashReportingEnabled_enabledInBuild() { + // When + clearExistingInstance() + val settings = Settings.getInstance(testContext, isCrashReportEnabledInBuild = true) + .apply(Settings::clear) + + // Then + assertTrue(settings.isCrashReportingEnabled) + } + + @Test + fun isCrashReportingEnabled_disabledInBuild() { + // When + clearExistingInstance() + val settings = Settings.getInstance(testContext, isCrashReportEnabledInBuild = false) + .apply(Settings::clear) + + // Then + assertFalse(settings.isCrashReportingEnabled) + } + + @Test + fun isRemoteDebuggingEnabled() { + // When just created + // Then + assertFalse(settings.isRemoteDebuggingEnabled) + } + + @Test + fun isTelemetryEnabled() { + // When just created + // Then + assertTrue(settings.isTelemetryEnabled) + } + + @Test + fun autoBounceQuickActionSheetCount() { + // When just created + // Then + assertEquals(0, settings.autoBounceQuickActionSheetCount) + + // When + settings.incrementAutomaticBounceQuickActionSheetCount() + settings.incrementAutomaticBounceQuickActionSheetCount() + + // Then + assertEquals(2, settings.autoBounceQuickActionSheetCount) + } + + @Test + fun shouldAutoBounceQuickActionSheet() { + // When just created + // Then + assertTrue(settings.shouldAutoBounceQuickActionSheet) + + // When + settings.incrementAutomaticBounceQuickActionSheetCount() + + // Then + assertTrue(settings.shouldAutoBounceQuickActionSheet) + + // When + settings.incrementAutomaticBounceQuickActionSheetCount() + + // Then + assertFalse(settings.shouldAutoBounceQuickActionSheet) + } + + @Test + fun shouldUseLightTheme() { + // When just created + // Then + assertFalse(settings.shouldUseLightTheme) + + // When + settings.setLightTheme(true) + + // Then + assertTrue(settings.shouldUseLightTheme) + } + + @Test + fun shouldUseAutoSize() { + // When just created + // Then + assertTrue(settings.shouldUseAutoSize) + + // When + settings.setAutoSize(false) + + // Then + assertFalse(settings.shouldUseAutoSize) + } + + @Test + fun fontSizeFactor() { + // When just created + // Then + assertEquals(1f, settings.fontSizeFactor) + + // When + settings.setFontSizeFactor(2f) + + // Then + assertEquals(2f, settings.fontSizeFactor) + } + + @Test + fun shouldShowVisitedSitesBookmarks() { + // When just created + // Then + assertTrue(settings.shouldShowVisitedSitesBookmarks) + } + + @Test + fun shouldUseDarkTheme() { + // When just created + // Then + assertFalse(settings.shouldUseDarkTheme) + } + + @Test + fun shouldFollowDeviceTheme() { + // When just created + // Then + assertFalse(settings.shouldFollowDeviceTheme) + + // When + settings.setFollowDeviceTheme(true) + + // Then + assertTrue(settings.shouldFollowDeviceTheme) + } + + @Test + fun shouldUseTrackingProtection() { + // When + // Then + assertTrue(settings.shouldUseTrackingProtection) + + // When + settings.setTrackingProtection(false) + + // Then + assertFalse(settings.shouldUseTrackingProtection) + } + + @Test + fun shouldUseAutoBatteryTheme() { + // When just created + // Then + assertFalse(settings.shouldUseAutoBatteryTheme) + } + + @Test + fun showSearchSuggestions() { + // When just created + // Then + assertTrue(settings.showSearchSuggestions()) + } + + @Test + fun sitePermissionsPhoneFeatureCameraAction() { + // When just created + // Then + assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureCameraAction()) + + // When + settings.setSitePermissionsPhoneFeatureCameraAction(BLOCKED) + + // Then + assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureCameraAction()) + } + + @Test + fun sitePermissionsPhoneFeatureMicrophoneAction() { + // When just created + // Then + assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureMicrophoneAction()) + + // When + settings.setSitePermissionsPhoneFeatureMicrophoneAction(BLOCKED) + + // Then + assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureMicrophoneAction()) + } + + @Test + fun sitePermissionsPhoneFeatureNotificationAction() { + // When just created + // Then + assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureNotificationAction()) + + // When + settings.setSitePermissionsPhoneFeatureNotificationAction(BLOCKED) + + // Then + assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureNotificationAction()) + } + + @Test + fun sitePermissionsPhoneFeatureLocation() { + // When just created + // Then + assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureLocation()) + + // When + settings.setSitePermissionsPhoneFeatureLocation(BLOCKED) + + // Then + assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureLocation()) + } + + @Test + fun getSitePermissionsCustomSettingsRules_default() { + // When just created + // Then + assertEquals( + allAskToAllow(), + settings.getSitePermissionsCustomSettingsRules() + ) + } + + @Test + fun getSitePermissionsCustomSettingsRules_camera() { + // When + settings.setSitePermissionsPhoneFeatureCameraAction(BLOCKED) + + // Then + assertEquals( + allAskToAllow().copy(camera = BLOCKED), + settings.getSitePermissionsCustomSettingsRules() + ) + } + + @Test + fun getSitePermissionsCustomSettingsRules_notification() { + // When + settings.setSitePermissionsPhoneFeatureNotificationAction(BLOCKED) + + // Then + assertEquals( + allAskToAllow().copy(notification = BLOCKED), + settings.getSitePermissionsCustomSettingsRules() + ) + } + + @Test + fun getSitePermissionsCustomSettingsRules_location() { + // When + settings.setSitePermissionsPhoneFeatureLocation(BLOCKED) + + // Then + assertEquals( + allAskToAllow().copy(location = BLOCKED), + settings.getSitePermissionsCustomSettingsRules() + ) + } + + @Test + fun getSitePermissionsCustomSettingsRules_microphone() { + // When + settings.setSitePermissionsPhoneFeatureMicrophoneAction(BLOCKED) + + // Then + assertEquals( + allAskToAllow().copy(microphone = BLOCKED), + settings.getSitePermissionsCustomSettingsRules() + ) + } +} + +private fun clearExistingInstance() { + Settings.instance = null +} + +private fun Settings.clear() { + preferences.clearAndCommit() +} + +private fun allAskToAllow() = SitePermissionsRules( + camera = ASK_TO_ALLOW, + location = ASK_TO_ALLOW, + microphone = ASK_TO_ALLOW, + notification = ASK_TO_ALLOW +) \ No newline at end of file diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index d591be99f..b8d7a37ed 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -26,6 +26,7 @@ private object Versions { const val androidx_recyclerview = "1.1.0-alpha06" const val androidx_lifecycle_savedstate = "1.0.0-alpha01" const val androidx_testing = "1.1.0-alpha08" + const val androidx_test_ext = "1.0.0" const val androidx_core = "1.1.0-rc01" const val androidx_transition = "1.1.0-rc02" const val google_material = "1.1.0-alpha07" @@ -131,6 +132,7 @@ object Deps { const val mozilla_support_base = "org.mozilla.components:support-base:${Versions.mozilla_android_components}" const val mozilla_support_ktx = "org.mozilla.components:support-ktx:${Versions.mozilla_android_components}" const val mozilla_support_rustlog = "org.mozilla.components:support-rustlog:${Versions.mozilla_android_components}" + const val mozilla_support_test = "org.mozilla.components:support-test:${Versions.mozilla_android_components}" const val sentry = "io.sentry:sentry-android:${Versions.sentry}" const val leakcanary = "com.squareup.leakcanary:leakcanary-android:${Versions.leakcanary}" @@ -187,6 +189,7 @@ object Deps { const val uiautomator = "com.android.support.test.uiautomator:uiautomator-v18:${Versions.uiautomator}" const val robolectric = "org.robolectric:robolectric:${Versions.robolectric}" const val fragment_testing = "androidx.fragment:fragment-testing:${Versions.androidx_testing}" + const val androidx_junit = "androidx.test.ext:junit:${Versions.androidx_test_ext}" const val places_forUnitTests = "org.mozilla.appservices:places-forUnitTests:${Versions.mozilla_appservices}" const val google_ads_id = "com.google.android.gms:play-services-ads-identifier:${Versions.google_ads_id_version}"