commit f320908698fa6febcb43357ef3155a8988d65b40
parent 2c67a14f5a0a94e346e7acc14abb356ac53827b7
Author: mcarare <48995920+mcarare@users.noreply.github.com>
Date: Mon, 3 Nov 2025 08:05:39 +0000
Bug 1996630 - Inject Settings into TrackingProtectionPanelView. r=android-reviewers,avirvara,anpopa
This patch refactors `TrackingProtectionPanelView` to receive a `Settings` object via its constructor instead of accessing it through a `Context` extension function.
This change improves testability by allowing a mocked `Settings` object to be injected directly, removing the need for `mockkStatic` in `TrackingProtectionPanelViewTest`.
Differential Revision: https://phabricator.services.mozilla.com/D270863
Diffstat:
4 files changed, 59 insertions(+), 125 deletions(-)
diff --git a/mobile/android/fenix/app/lint-baseline.xml b/mobile/android/fenix/app/lint-baseline.xml
@@ -378,61 +378,6 @@
<issue
id="NoStaticMocking"
message="Usage of MockK's 'mockkStatic' for static mocking is discouraged. Refactor to use dependency injection."
- errorLine1=" mockkStatic("org.mozilla.fenix.ext.ContextKt") {"
- errorLine2=" ^">
- <location
- file="src/test/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelViewTest.kt"
- line="62"
- column="9"/>
- </issue>
-
- <issue
- id="NoStaticMocking"
- message="Usage of MockK's 'mockkStatic' for static mocking is discouraged. Refactor to use dependency injection."
- errorLine1=" mockkStatic("org.mozilla.fenix.ext.ContextKt") {"
- errorLine2=" ^">
- <location
- file="src/test/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelViewTest.kt"
- line="76"
- column="9"/>
- </issue>
-
- <issue
- id="NoStaticMocking"
- message="Usage of MockK's 'mockkStatic' for static mocking is discouraged. Refactor to use dependency injection."
- errorLine1=" mockkStatic("org.mozilla.fenix.ext.ContextKt") {"
- errorLine2=" ^">
- <location
- file="src/test/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelViewTest.kt"
- line="91"
- column="9"/>
- </issue>
-
- <issue
- id="NoStaticMocking"
- message="Usage of MockK's 'mockkStatic' for static mocking is discouraged. Refactor to use dependency injection."
- errorLine1=" mockkStatic("org.mozilla.fenix.ext.ContextKt") {"
- errorLine2=" ^">
- <location
- file="src/test/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelViewTest.kt"
- line="132"
- column="9"/>
- </issue>
-
- <issue
- id="NoStaticMocking"
- message="Usage of MockK's 'mockkStatic' for static mocking is discouraged. Refactor to use dependency injection."
- errorLine1=" mockkStatic("org.mozilla.fenix.ext.ContextKt") {"
- errorLine2=" ^">
- <location
- file="src/test/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelViewTest.kt"
- line="155"
- column="9"/>
- </issue>
-
- <issue
- id="NoStaticMocking"
- message="Usage of MockK's 'mockkStatic' for static mocking is discouraged. Refactor to use dependency injection."
errorLine1=" mockkStatic("mozilla.components.support.ktx.android.util.DisplayMetricsKt")"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelDialogFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelDialogFragment.kt
@@ -48,6 +48,7 @@ import org.mozilla.fenix.components.StoreProvider
import org.mozilla.fenix.databinding.FragmentTrackingProtectionBinding
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.requireComponents
+import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.settings.SupportUtils
import com.google.android.material.R as materialR
@@ -116,7 +117,11 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), UserInt
)
val binding = FragmentTrackingProtectionBinding.bind(view)
trackingProtectionView =
- TrackingProtectionPanelView(binding.fragmentTp, trackingProtectionInteractor)
+ TrackingProtectionPanelView(
+ containerView = binding.fragmentTp,
+ settings = requireContext().settings(),
+ interactor = trackingProtectionInteractor,
+ )
tab?.let { updateTrackers(it) }
return view
}
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelView.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelView.kt
@@ -25,7 +25,6 @@ import org.mozilla.fenix.GleanMetrics.TrackingProtection
import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.ComponentTrackingProtectionPanelBinding
import org.mozilla.fenix.ext.addUnderline
-import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.CROSS_SITE_TRACKING_COOKIES
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.CRYPTOMINERS
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.FINGERPRINTERS
@@ -33,6 +32,7 @@ import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.REDIRECT_
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.SOCIAL_MEDIA_TRACKERS
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.SUSPECTED_FINGERPRINTERS
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.TRACKING_CONTENT
+import org.mozilla.fenix.utils.Settings
/**
* Interface for the TrackingProtectionPanelViewInteractor. This interface is implemented by objects that want
@@ -73,6 +73,7 @@ interface TrackingProtectionPanelViewInteractor {
@SuppressWarnings("TooManyFunctions")
class TrackingProtectionPanelView(
val containerView: ViewGroup,
+ val settings: Settings,
val interactor: TrackingProtectionPanelInteractor,
) : View.OnClickListener {
@@ -133,7 +134,7 @@ class TrackingProtectionPanelView(
binding.notBlockingHeader.isGone = bucketedTrackers.loadedIsEmpty()
binding.blockingHeader.isGone = bucketedTrackers.blockedIsEmpty()
- if (containerView.context.settings().enabledTotalCookieProtection) {
+ if (settings.enabledTotalCookieProtection) {
binding.crossSiteTracking.text = containerView.context.getString(R.string.etp_cookies_title_2)
binding.crossSiteTrackingLoaded.text = containerView.context.getString(R.string.etp_cookies_title_2)
}
@@ -151,7 +152,7 @@ class TrackingProtectionPanelView(
binding.detailsMode.visibility = View.VISIBLE
if (category == CROSS_SITE_TRACKING_COOKIES &&
- containerView.context.settings().enabledTotalCookieProtection
+ settings.enabledTotalCookieProtection
) {
binding.categoryTitle.setText(R.string.etp_cookies_title_2)
binding.categoryDescription.setText(R.string.etp_cookies_description_2)
diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelViewTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/trackingprotection/TrackingProtectionPanelViewTest.kt
@@ -4,13 +4,11 @@
package org.mozilla.fenix.trackingprotection
-import android.content.Context
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.view.isVisible
import io.mockk.every
import io.mockk.mockk
-import io.mockk.mockkStatic
import io.mockk.verify
import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert.assertEquals
@@ -25,16 +23,17 @@ import org.junit.runner.RunWith
import org.mozilla.fenix.GleanMetrics.TrackingProtection
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
-import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.helpers.FenixGleanTestRule
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.CROSS_SITE_TRACKING_COOKIES
import org.mozilla.fenix.trackingprotection.TrackingProtectionCategory.SOCIAL_MEDIA_TRACKERS
+import org.mozilla.fenix.utils.Settings
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class TrackingProtectionPanelViewTest {
private lateinit var container: ViewGroup
+ private lateinit var settings: Settings
private lateinit var interactor: TrackingProtectionPanelInteractor
private lateinit var view: TrackingProtectionPanelView
private val baseState = ProtectionsState(
@@ -54,51 +53,42 @@ class TrackingProtectionPanelViewTest {
fun setup() {
container = FrameLayout(testContext)
interactor = mockk(relaxUnitFun = true)
- view = TrackingProtectionPanelView(container, interactor)
+ settings = mockk(relaxed = true)
+ view = TrackingProtectionPanelView(container, settings = settings, interactor)
}
@Test
fun testNormalModeUi() {
- mockkStatic("org.mozilla.fenix.ext.ContextKt") {
- every { any<Context>().settings() } returns mockk(relaxed = true)
-
- view.update(baseState.copy(mode = ProtectionsState.Mode.Normal))
- assertFalse(view.binding.detailsMode.isVisible)
- assertTrue(view.binding.normalMode.isVisible)
- assertTrue(view.binding.protectionSettings.isVisible)
- assertFalse(view.binding.notBlockingHeader.isVisible)
- assertFalse(view.binding.blockingHeader.isVisible)
- }
+ view.update(baseState.copy(mode = ProtectionsState.Mode.Normal))
+ assertFalse(view.binding.detailsMode.isVisible)
+ assertTrue(view.binding.normalMode.isVisible)
+ assertTrue(view.binding.protectionSettings.isVisible)
+ assertFalse(view.binding.notBlockingHeader.isVisible)
+ assertFalse(view.binding.blockingHeader.isVisible)
}
@Test
fun testNormalModeUiCookiesWithTotalCookieProtectionEnabled() {
- mockkStatic("org.mozilla.fenix.ext.ContextKt") {
- every { any<Context>().settings() } returns mockk {
- every { enabledTotalCookieProtection } returns true
- }
- val expectedTitle = testContext.getString(R.string.etp_cookies_title_2)
+ every { settings.enabledTotalCookieProtection } returns true
- view.update(baseState.copy(mode = ProtectionsState.Mode.Normal))
+ val expectedTitle = testContext.getString(R.string.etp_cookies_title_2)
- assertEquals(expectedTitle, view.binding.crossSiteTracking.text)
- assertEquals(expectedTitle, view.binding.crossSiteTrackingLoaded.text)
- }
+ view.update(baseState.copy(mode = ProtectionsState.Mode.Normal))
+
+ assertEquals(expectedTitle, view.binding.crossSiteTracking.text)
+ assertEquals(expectedTitle, view.binding.crossSiteTrackingLoaded.text)
}
@Test
fun testNormalModeUiCookiesWithTotalCookieProtectionDisabled() {
- mockkStatic("org.mozilla.fenix.ext.ContextKt") {
- every { any<Context>().settings() } returns mockk {
- every { enabledTotalCookieProtection } returns false
- }
- val expectedTitle = testContext.getString(R.string.etp_cookies_title)
+ every { settings.enabledTotalCookieProtection } returns false
+
+ val expectedTitle = testContext.getString(R.string.etp_cookies_title)
- view.update(baseState.copy(mode = ProtectionsState.Mode.Normal))
+ view.update(baseState.copy(mode = ProtectionsState.Mode.Normal))
- assertEquals(expectedTitle, view.binding.crossSiteTracking.text)
- assertEquals(expectedTitle, view.binding.crossSiteTrackingLoaded.text)
- }
+ assertEquals(expectedTitle, view.binding.crossSiteTracking.text)
+ assertEquals(expectedTitle, view.binding.crossSiteTrackingLoaded.text)
}
@Test
@@ -129,48 +119,41 @@ class TrackingProtectionPanelViewTest {
@Test
fun testPrivateModeUiCookiesWithTotalCookieProtectionEnabled() {
- mockkStatic("org.mozilla.fenix.ext.ContextKt") {
- every { any<Context>().settings() } returns mockk {
- every { enabledTotalCookieProtection } returns true
- }
- val expectedTitle = testContext.getString(R.string.etp_cookies_title_2)
- val expectedDescription = testContext.getString(R.string.etp_cookies_description_2)
-
- view.update(
- baseState.copy(
- mode = ProtectionsState.Mode.Details(
- selectedCategory = CROSS_SITE_TRACKING_COOKIES,
- categoryBlocked = false,
- ),
+ every { settings.enabledTotalCookieProtection } returns true
+ val expectedTitle = testContext.getString(R.string.etp_cookies_title_2)
+ val expectedDescription = testContext.getString(R.string.etp_cookies_description_2)
+
+ view.update(
+ baseState.copy(
+ mode = ProtectionsState.Mode.Details(
+ selectedCategory = CROSS_SITE_TRACKING_COOKIES,
+ categoryBlocked = false,
),
- )
+ ),
+ )
- assertEquals(expectedTitle, view.binding.categoryTitle.text)
- assertEquals(expectedDescription, view.binding.categoryDescription.text)
- }
+ assertEquals(expectedTitle, view.binding.categoryTitle.text)
+ assertEquals(expectedDescription, view.binding.categoryDescription.text)
}
@Test
fun testPrivateModeUiCookiesWithTotalCookieProtectionDisabled() {
- mockkStatic("org.mozilla.fenix.ext.ContextKt") {
- every { any<Context>().settings() } returns mockk {
- every { enabledTotalCookieProtection } returns false
- }
- val expectedTitle = testContext.getString(R.string.etp_cookies_title)
- val expectedDescription = testContext.getString(R.string.etp_cookies_description)
-
- view.update(
- baseState.copy(
- mode = ProtectionsState.Mode.Details(
- selectedCategory = CROSS_SITE_TRACKING_COOKIES,
- categoryBlocked = false,
- ),
+ every { settings.enabledTotalCookieProtection } returns false
+
+ val expectedTitle = testContext.getString(R.string.etp_cookies_title)
+ val expectedDescription = testContext.getString(R.string.etp_cookies_description)
+
+ view.update(
+ baseState.copy(
+ mode = ProtectionsState.Mode.Details(
+ selectedCategory = CROSS_SITE_TRACKING_COOKIES,
+ categoryBlocked = false,
),
- )
+ ),
+ )
- assertEquals(expectedTitle, view.binding.categoryTitle.text)
- assertEquals(expectedDescription, view.binding.categoryDescription.text)
- }
+ assertEquals(expectedTitle, view.binding.categoryTitle.text)
+ assertEquals(expectedDescription, view.binding.categoryDescription.text)
}
@Test