Fix DataUsageListTest

Using androidx.fragment.app.testing.launchFragment to rewrite the test.

Bug: 315449973
Test: manual - on DataUsageList
Test: unit test
Change-Id: Ief373becb4ac8ab1ba93b8ff3c594b5682c4821e
diff --git a/src/com/android/settings/datausage/DataUsageList.kt b/src/com/android/settings/datausage/DataUsageList.kt
index 6a187d8..3083fb7 100644
--- a/src/com/android/settings/datausage/DataUsageList.kt
+++ b/src/com/android/settings/datausage/DataUsageList.kt
@@ -30,6 +30,7 @@
 import androidx.fragment.app.viewModels
 import androidx.preference.Preference
 import com.android.settings.R
+import com.android.settings.dashboard.DashboardFragment
 import com.android.settings.datausage.lib.BillingCycleRepository
 import com.android.settings.datausage.lib.NetworkUsageData
 import com.android.settings.network.MobileNetworkRepository
@@ -45,43 +46,42 @@
  * to inspect based on usage cycle and control through [NetworkPolicy].
  */
 @OpenForTesting
-open class DataUsageList : DataUsageBaseFragment() {
-    @JvmField
+open class DataUsageList : DashboardFragment() {
     @VisibleForTesting
     var template: NetworkTemplate? = null
+        private set
 
-    @JvmField
     @VisibleForTesting
     var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+        private set
 
-    private lateinit var usageAmount: Preference
-    private var subscriptionInfoEntity: SubscriptionInfoEntity? = null
-    private lateinit var dataUsageListAppsController: DataUsageListAppsController
-    private lateinit var chartDataUsagePreferenceController: ChartDataUsagePreferenceController
     private lateinit var billingCycleRepository: BillingCycleRepository
 
-    private val viewModel: DataUsageListViewModel by viewModels()
+    private var usageAmount: Preference? = null
+    private var subscriptionInfoEntity: SubscriptionInfoEntity? = null
+    private var dataUsageListAppsController: DataUsageListAppsController? = null
+    private var chartDataUsagePreferenceController: ChartDataUsagePreferenceController? = null
+    private var dataUsageListHeaderController: DataUsageListHeaderController? = null
 
-    @VisibleForTesting
-    var dataUsageListHeaderController: DataUsageListHeaderController? = null
+    private val viewModel: DataUsageListViewModel by viewModels()
 
     override fun getMetricsCategory() = SettingsEnums.DATA_USAGE_LIST
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
+        billingCycleRepository = BillingCycleRepository(requireContext())
         if (requireContext().userManager.isGuestUser) {
             Log.e(TAG, "This setting isn't available for guest user")
             EventLog.writeEvent(0x534e4554, "262741858", -1 /* UID */, "Guest user")
             finish()
             return
         }
-        billingCycleRepository = createBillingCycleRepository()
         if (!billingCycleRepository.isBandwidthControlEnabled()) {
             Log.w(TAG, "No bandwidth control; leaving")
             finish()
             return
         }
-        usageAmount = findPreference(KEY_USAGE_AMOUNT)!!
+        usageAmount = findPreference(KEY_USAGE_AMOUNT)
         processArgument()
         val template = template
         if (template == null) {
@@ -94,12 +94,9 @@
             init(template)
         }
         chartDataUsagePreferenceController = use(ChartDataUsagePreferenceController::class.java)
-        chartDataUsagePreferenceController.init(template)
+            .apply { init(template) }
     }
 
-    @VisibleForTesting
-    open fun createBillingCycleRepository() = BillingCycleRepository(requireContext())
-
     override fun onViewCreated(v: View, savedInstanceState: Bundle?) {
         super.onViewCreated(v, savedInstanceState)
 
@@ -117,10 +114,10 @@
             ::updateSelectedCycle,
         )
         viewModel.cyclesFlow.collectLatestWithLifecycle(viewLifecycleOwner) { cycles ->
-            dataUsageListAppsController.updateCycles(cycles)
+            dataUsageListAppsController?.updateCycles(cycles)
         }
         viewModel.chartDataFlow.collectLatestWithLifecycle(viewLifecycleOwner) { chartData ->
-            chartDataUsagePreferenceController.update(chartData)
+            chartDataUsagePreferenceController?.update(chartData)
         }
     }
 
@@ -128,7 +125,7 @@
 
     override fun getLogTag() = TAG
 
-    fun processArgument() {
+    private fun processArgument() {
         arguments?.let {
             subId = it.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID)
             template = it.getParcelable(EXTRA_NETWORK_TEMPLATE, NetworkTemplate::class.java)
@@ -145,8 +142,7 @@
         }
     }
 
-    @VisibleForTesting
-    open fun updateSubscriptionInfoEntity() {
+    private fun updateSubscriptionInfoEntity() {
         ThreadUtils.postOnBackgroundThread {
             subscriptionInfoEntity =
                 MobileNetworkRepository.getInstance(context).getSubInfoById(subId.toString())
@@ -154,19 +150,16 @@
     }
 
     /** Update chart sweeps and cycle list to reflect [NetworkPolicy] for current [template]. */
-    @VisibleForTesting
-    fun updatePolicy() {
+    private fun updatePolicy() {
         val isBillingCycleModifiable = isBillingCycleModifiable()
         dataUsageListHeaderController?.setConfigButtonVisible(isBillingCycleModifiable)
-        chartDataUsagePreferenceController.setBillingCycleModifiable(isBillingCycleModifiable)
+        chartDataUsagePreferenceController?.setBillingCycleModifiable(isBillingCycleModifiable)
     }
 
-    @VisibleForTesting
-    open fun isBillingCycleModifiable(): Boolean {
-        return (billingCycleRepository.isModifiable(subId) &&
+    private fun isBillingCycleModifiable(): Boolean =
+        billingCycleRepository.isModifiable(subId) &&
             requireContext().getSystemService(SubscriptionManager::class.java)!!
-                .getActiveSubscriptionInfo(subId) != null)
-    }
+                .getActiveSubscriptionInfo(subId) != null
 
     /**
      * Updates the chart and detail data when initial loaded or selected cycle changed.
@@ -174,7 +167,7 @@
     private fun updateSelectedCycle(usageData: NetworkUsageData) {
         Log.d(TAG, "showing cycle $usageData")
 
-        usageAmount.title = usageData.getDataUsedString(requireContext())
+        usageAmount?.title = usageData.getDataUsedString(requireContext())
         viewModel.selectedCycleFlow.value = usageData
 
         updateApps(usageData)
@@ -182,7 +175,7 @@
 
     /** Updates applications data usage. */
     private fun updateApps(usageData: NetworkUsageData) {
-        dataUsageListAppsController.update(
+        dataUsageListAppsController?.update(
             carrierId = subscriptionInfoEntity?.carrierId,
             startTime = usageData.startTime,
             endTime = usageData.endTime,
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.kt b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.kt
deleted file mode 100644
index 39b8446..0000000
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.kt
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.datausage
-
-import android.content.Context
-import android.content.Intent
-import android.net.NetworkTemplate
-import android.os.Bundle
-import android.os.UserManager
-import android.provider.Settings
-import androidx.preference.Preference
-import androidx.test.core.app.ApplicationProvider
-import com.android.settings.datausage.DataUsageListTest.ShadowDataUsageBaseFragment
-import com.android.settings.datausage.TemplatePreference.NetworkServices
-import com.android.settings.datausage.lib.BillingCycleRepository
-import com.android.settings.testutils.FakeFeatureFactory
-import com.android.settingslib.NetworkPolicyEditor
-import com.android.settingslib.core.AbstractPreferenceController
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.doNothing
-import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
-import org.mockito.Spy
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-import org.robolectric.RobolectricTestRunner
-import org.robolectric.annotation.Config
-import org.robolectric.annotation.Implementation
-import org.robolectric.annotation.Implements
-import org.robolectric.util.ReflectionHelpers
-
-@RunWith(RobolectricTestRunner::class)
-@Config(shadows = [ShadowDataUsageBaseFragment::class])
-class DataUsageListTest {
-    @get:Rule
-    val mockito: MockitoRule = MockitoJUnit.rule()
-
-    @Mock
-    private lateinit var networkServices: NetworkServices
-
-    @Mock
-    private lateinit var userManager: UserManager
-
-    @Mock
-    private lateinit var billingCycleRepository: BillingCycleRepository
-
-    @Mock
-    private lateinit var dataUsageListHeaderController: DataUsageListHeaderController
-
-    @Spy
-    private val context: Context = ApplicationProvider.getApplicationContext()
-
-    @Spy
-    private val dataUsageList = TestDataUsageList()
-
-    @Before
-    fun setUp() {
-        FakeFeatureFactory.setupForTest()
-        networkServices.mPolicyEditor = mock(NetworkPolicyEditor::class.java)
-        doReturn(context).`when`(dataUsageList).context
-        doReturn(userManager).`when`(context).getSystemService(UserManager::class.java)
-        doReturn(false).`when`(userManager).isGuestUser
-        ReflectionHelpers.setField(dataUsageList, "services", networkServices)
-        doNothing().`when`(dataUsageList).updateSubscriptionInfoEntity()
-        `when`(billingCycleRepository.isBandwidthControlEnabled()).thenReturn(true)
-        dataUsageList.dataUsageListHeaderController = dataUsageListHeaderController
-    }
-
-    @Test
-    fun onCreate_isNotGuestUser_shouldNotFinish() {
-        dataUsageList.template = mock<NetworkTemplate>(NetworkTemplate::class.java)
-        doReturn(false).`when`(userManager).isGuestUser
-        doNothing().`when`(dataUsageList).processArgument()
-        dataUsageList.onCreate(null)
-        verify(dataUsageList, never()).finish()
-    }
-
-    @Test
-    fun onCreate_isGuestUser_shouldFinish() {
-        doReturn(true).`when`(userManager).isGuestUser
-        dataUsageList.onCreate(null)
-        verify(dataUsageList).finish()
-    }
-
-    @Test
-    fun processArgument_shouldGetTemplateFromArgument() {
-        val args = Bundle()
-        args.putParcelable(
-            DataUsageList.EXTRA_NETWORK_TEMPLATE, mock(
-                NetworkTemplate::class.java
-            )
-        )
-        args.putInt(DataUsageList.EXTRA_SUB_ID, 3)
-        dataUsageList.arguments = args
-        dataUsageList.processArgument()
-        assertThat(dataUsageList.template).isNotNull()
-        assertThat(dataUsageList.subId).isEqualTo(3)
-    }
-
-    @Test
-    fun processArgument_fromIntent_shouldGetTemplateFromIntent() {
-        val intent = Intent()
-        intent.putExtra(
-            Settings.EXTRA_NETWORK_TEMPLATE, mock(
-                NetworkTemplate::class.java
-            )
-        )
-        intent.putExtra(Settings.EXTRA_SUB_ID, 3)
-        doReturn(intent).`when`(dataUsageList).intent
-        dataUsageList.processArgument()
-        assertThat(dataUsageList.template).isNotNull()
-        assertThat(dataUsageList.subId).isEqualTo(3)
-    }
-
-    @Test
-    fun updatePolicy_setConfigButtonVisible() {
-        dataUsageList.template = mock(NetworkTemplate::class.java)
-        dataUsageList.onCreate(null)
-
-        dataUsageList.updatePolicy()
-
-        verify(dataUsageListHeaderController).setConfigButtonVisible(true)
-    }
-
-    @Implements(DataUsageBaseFragment::class)
-    class ShadowDataUsageBaseFragment {
-        @Implementation
-        fun onCreate(@Suppress("UNUSED_PARAMETER") icicle: Bundle?) {
-            // do nothing
-        }
-    }
-
-    open inner class TestDataUsageList : DataUsageList() {
-        override fun <T : AbstractPreferenceController?> use(clazz: Class<T>): T = mock(clazz)
-
-        @Suppress("UNCHECKED_CAST")
-        override fun <T : Preference?> findPreference(key: CharSequence): T =
-            mock(Preference::class.java) as T
-
-        public override fun getIntent() = Intent()
-
-        override fun createBillingCycleRepository() = billingCycleRepository
-
-        override fun isBillingCycleModifiable() = true
-    }
-}
diff --git a/tests/spa_unit/Android.bp b/tests/spa_unit/Android.bp
index c3e99f7..4df6254 100644
--- a/tests/spa_unit/Android.bp
+++ b/tests/spa_unit/Android.bp
@@ -34,6 +34,7 @@
         "androidx.compose.runtime_runtime",
         "androidx.test.ext.junit",
         "androidx.test.runner",
+        "androidx.fragment_fragment-testing",
         "flag-junit",
         "mockito-target-extended-minus-junit4",
     ],
diff --git a/tests/spa_unit/src/com/android/settings/datausage/DataUsageListTest.kt b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListTest.kt
new file mode 100644
index 0000000..29ec0ee
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListTest.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.datausage
+
+import android.content.Context
+import android.content.Intent
+import android.net.NetworkTemplate
+import android.os.UserManager
+import android.provider.Settings
+import android.telephony.SubscriptionManager
+import androidx.core.os.bundleOf
+import androidx.fragment.app.testing.launchFragment
+import androidx.fragment.app.testing.withFragment
+import androidx.lifecycle.Lifecycle
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spaprivileged.framework.common.userManager
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+
+private val mockUserManager: UserManager = mock<UserManager>()
+
+private val mockContext: Context = spy(ApplicationProvider.getApplicationContext()) {
+    on { userManager } doReturn mockUserManager
+}
+
+private var fakeIntent = Intent()
+
+@RunWith(AndroidJUnit4::class)
+class DataUsageListTest {
+
+    @Before
+    fun setUp() {
+        mockUserManager.stub {
+            on { isGuestUser } doReturn false
+        }
+        fakeIntent = Intent()
+    }
+
+    @Test
+    fun launchFragment_withoutArguments_finish() {
+        val scenario = launchFragment<TestDataUsageList>(initialState = Lifecycle.State.CREATED)
+
+        scenario.withFragment {
+            assertThat(template).isNull()
+            assertThat(subId).isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+            assertThat(activity!!.isFinishing).isTrue()
+        }
+    }
+
+    @Test
+    fun launchFragment_isGuestUser_finish() {
+        mockUserManager.stub {
+            on { isGuestUser } doReturn true
+        }
+        val fragmentArgs = bundleOf(
+            DataUsageList.EXTRA_NETWORK_TEMPLATE to mock<NetworkTemplate>(),
+            DataUsageList.EXTRA_SUB_ID to 3,
+        )
+
+        val scenario = launchFragment<TestDataUsageList>(
+            fragmentArgs = fragmentArgs,
+            initialState = Lifecycle.State.CREATED,
+        )
+
+        scenario.withFragment {
+            assertThat(activity!!.isFinishing).isTrue()
+        }
+    }
+
+    @Test
+    fun launchFragment_withArguments_getTemplateFromArgument() {
+        val fragmentArgs = bundleOf(
+            DataUsageList.EXTRA_NETWORK_TEMPLATE to mock<NetworkTemplate>(),
+            DataUsageList.EXTRA_SUB_ID to 3,
+        )
+
+        val scenario = launchFragment<TestDataUsageList>(
+            fragmentArgs = fragmentArgs,
+            initialState = Lifecycle.State.CREATED,
+        )
+
+        scenario.withFragment {
+            assertThat(template).isNotNull()
+            assertThat(subId).isEqualTo(3)
+            assertThat(activity!!.isFinishing).isFalse()
+        }
+    }
+
+    @Test
+    fun launchFragment_withIntent_getTemplateFromIntent() {
+        fakeIntent = Intent().apply {
+            putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mock<NetworkTemplate>())
+            putExtra(Settings.EXTRA_SUB_ID, 2)
+        }
+
+        val scenario = launchFragment<TestDataUsageList>(initialState = Lifecycle.State.CREATED)
+
+        scenario.withFragment {
+            assertThat(template).isNotNull()
+            assertThat(subId).isEqualTo(2)
+            assertThat(activity!!.isFinishing).isFalse()
+        }
+    }
+}
+
+class TestDataUsageList : DataUsageList() {
+    override fun getContext() = mockContext
+
+    override fun getIntent() = fakeIntent
+}