Added UI tests for FingerprintEnrollIntro

Test: m -j40 RunSettingsRoboTests ROBOTEST_FILTER=FingerprintEnrollmentIntroFragmentTest
Bug: 295206367
Change-Id: I70f6b50dd2604e01805df04ffb1c07a9134ba065
This commit is contained in:
Joshua McCloskey
2023-08-28 20:36:09 +00:00
parent 9952d054d9
commit b7021c8e0b
6 changed files with 414 additions and 215 deletions

View File

@@ -16,199 +16,210 @@
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="?attr/fingerprint_layout_theme"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
style="@style/SudContentFrame"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/setup_wizard_layout"
style="?attr/fingerprint_layout_theme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
android:layout_height="match_parent">
<com.google.android.setupdesign.view.RichTextView
android:id="@+id/error_text"
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
style="@style/SudContentIllustration"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@null"
android:src="@drawable/fingerprint_enroll_introduction" />
</FrameLayout>
<!-- Contains the extra information text at the bottom -->
<LinearLayout
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<!-- How it works -->
<TextView
<com.google.android.setupdesign.view.RichTextView
android:id="@+id/error_text"
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BiometricEnrollIntroTitle"
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_title_2" />
android:layout_height="wrap_content" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
style="@style/SudContentIllustration"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@null"
android:src="@drawable/fingerprint_enroll_introduction" />
</FrameLayout>
<!-- Contains the extra information text at the bottom -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="vertical">
<ImageView
android:id="@+id/icon_fingerprint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_fingerprint_24dp"/>
<Space
android:layout_width="16dp"
android:layout_height="wrap_content"/>
<!-- How it works -->
<TextView
android:id="@+id/footer_message_2"
style="@style/BiometricEnrollIntroTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BiometricEnrollIntroMessage" />
</LinearLayout>
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_title_2" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_device_locked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_lock_24dp"/>
<Space
android:layout_width="16dp"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/footer_message_3"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BiometricEnrollIntroMessage" />
</LinearLayout>
android:orientation="horizontal">
<!-- You're in control -->
<TextView
android:id="@+id/footer_title_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BiometricEnrollIntroTitle" />
<ImageView
android:id="@+id/icon_fingerprint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_fingerprint_24dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Space
android:layout_width="16dp"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/icon_trash_can"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_trash_can"/>
<Space
android:layout_width="16dp"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/footer_message_4"
<TextView
android:id="@+id/footer_message_2"
style="@style/BiometricEnrollIntroMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BiometricEnrollIntroMessage" />
</LinearLayout>
android:orientation="horizontal">
<!-- Keep in mind -->
<TextView
android:id="@+id/footer_title_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BiometricEnrollIntroTitle"
android:text="@string/security_settings_face_enroll_introduction_info_title"/>
<ImageView
android:id="@+id/icon_device_locked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_lock_24dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Space
android:layout_width="16dp"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/icon_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_info_outline_24dp"/>
<Space
android:layout_width="16dp"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/footer_message_3"
style="@style/BiometricEnrollIntroMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- You're in control -->
<TextView
android:id="@+id/footer_message_5"
android:id="@+id/footer_title_1"
style="@style/BiometricEnrollIntroTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BiometricEnrollIntroMessage" />
</LinearLayout>
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_trash_can"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_trash_can" />
<ImageView
android:id="@+id/icon_shield"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_guarantee"/>
<Space
android:layout_width="16dp"
android:layout_height="wrap_content"/>
<Space
android:layout_width="16dp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/footer_message_4"
style="@style/BiometricEnrollIntroMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- Keep in mind -->
<TextView
android:id="@+id/footer_message_6"
android:id="@+id/footer_title_2"
style="@style/BiometricEnrollIntroTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BiometricEnrollIntroMessage" />
</LinearLayout>
android:text="@string/security_settings_face_enroll_introduction_info_title" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_link_24dp"/>
<Space
android:layout_width="16dp"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/footer_learn_more"
android:linksClickable="true"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/BiometricEnrollIntroMessage"
android:paddingBottom="0dp"
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_message_learn_more" />
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_info_outline_24dp" />
<Space
android:layout_width="16dp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/footer_message_5"
style="@style/BiometricEnrollIntroMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_shield"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_guarantee" />
<Space
android:layout_width="16dp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/footer_message_6"
style="@style/BiometricEnrollIntroMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_link_24dp" />
<Space
android:layout_width="16dp"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/footer_learn_more"
style="@style/BiometricEnrollIntroMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:linksClickable="true"
android:paddingBottom="0dp"
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_message_learn_more" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -42,6 +42,7 @@ import com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST
import com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED
import com.android.settings.biometrics.GatekeeperPasswordProvider
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollConfirmationV2Fragment
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollEnrollingV2Fragment
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollFindSensorV2Fragment
@@ -82,6 +83,7 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
private lateinit var accessibilityViewModel: AccessibilityViewModel
private lateinit var foldStateViewModel: FoldStateViewModel
private lateinit var orientationStateViewModel: OrientationStateViewModel
private lateinit var fingerprintScrollViewModel: FingerprintScrollViewModel
private val coroutineDispatcher = Dispatchers.Default
/** Result listener for ChooseLock activity flow. */
@@ -210,8 +212,9 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
)[FingerprintEnrollViewModel::class.java]
// Initialize scroll view model
ViewModelProvider(this, FingerprintScrollViewModel.FingerprintScrollViewModelFactory())[
FingerprintScrollViewModel::class.java]
fingerprintScrollViewModel =
ViewModelProvider(this, FingerprintScrollViewModel.FingerprintScrollViewModelFactory())[
FingerprintScrollViewModel::class.java]
// Initialize AccessibilityViewModel
accessibilityViewModel =

View File

@@ -25,10 +25,13 @@ import android.os.Bundle
import android.text.Html
import android.text.method.LinkMovementMethod
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ScrollView
import android.widget.TextView
import androidx.annotation.VisibleForTesting
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
@@ -72,48 +75,69 @@ private data class TextModel(
* 2. How the data will be stored
* 3. How the user can access and remove their data
*/
class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll_introduction) {
private lateinit var footerBarMixin: FooterBarMixin
private lateinit var textModel: TextModel
private lateinit var navigationViewModel: FingerprintEnrollNavigationViewModel
private lateinit var fingerprintEnrollViewModel: FingerprintEnrollViewModel
private lateinit var fingerprintScrollViewModel: FingerprintScrollViewModel
private lateinit var gateKeeperViewModel: FingerprintGatekeeperViewModel
class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enroll_introduction) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
navigationViewModel =
ViewModelProvider(requireActivity())[FingerprintEnrollNavigationViewModel::class.java]
fingerprintEnrollViewModel =
ViewModelProvider(requireActivity())[FingerprintEnrollViewModel::class.java]
fingerprintScrollViewModel =
ViewModelProvider(requireActivity())[FingerprintScrollViewModel::class.java]
gateKeeperViewModel =
ViewModelProvider(requireActivity())[FingerprintGatekeeperViewModel::class.java]
/** Used for testing purposes */
private var factory: ViewModelProvider.Factory? = null
@VisibleForTesting
constructor(theFactory: ViewModelProvider.Factory) : this() {
factory = theFactory
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
private val viewModelProvider: ViewModelProvider by lazy {
if (factory != null) {
ViewModelProvider(requireActivity(), factory!!)
} else {
ViewModelProvider(requireActivity())
}
}
lifecycleScope.launch {
combine(
navigationViewModel.enrollType,
fingerprintEnrollViewModel.sensorType,
) { enrollType, sensorType ->
Pair(enrollType, sensorType)
}
.collect { (enrollType, sensorType) ->
textModel =
when (enrollType) {
Unicorn -> getUnicornTextModel()
else -> getNormalTextModel()
}
private lateinit var footerBarMixin: FooterBarMixin
private lateinit var textModel: TextModel
setupFooterBarAndScrollView(view)
// Note that the ViewModels cannot be requested before the onCreate call
private val navigationViewModel: FingerprintEnrollNavigationViewModel by lazy {
viewModelProvider[FingerprintEnrollNavigationViewModel::class.java]
}
private val fingerprintViewModel: FingerprintEnrollViewModel by lazy {
viewModelProvider[FingerprintEnrollViewModel::class.java]
}
private val fingerprintScrollViewModel: FingerprintScrollViewModel by lazy {
viewModelProvider[FingerprintScrollViewModel::class.java]
}
private val gateKeeperViewModel: FingerprintGatekeeperViewModel by lazy {
viewModelProvider[FingerprintGatekeeperViewModel::class.java]
}
if (savedInstanceState == null) {
getLayout()?.setHeaderText(textModel.headerText)
getLayout()?.setDescriptionText(textModel.descriptionText)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? =
super.onCreateView(inflater, container, savedInstanceState).also { theView ->
val view = theView!!
viewLifecycleOwner.lifecycleScope.launch {
combine(
navigationViewModel.enrollType,
fingerprintViewModel.sensorType,
) { enrollType, sensorType ->
Pair(enrollType, sensorType)
}
.collect { (enrollType, sensorType) ->
textModel =
when (enrollType) {
Unicorn -> getUnicornTextModel()
else -> getNormalTextModel()
}
setupFooterBarAndScrollView(view)
val layout = view as GlifLayout
layout.setHeaderText(textModel.headerText)
layout.setDescriptionText(textModel.descriptionText)
// Set color filter for the following icons.
val colorFilter = getIconColorFilter()
@@ -158,9 +182,9 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
view.requireViewById<TextView?>(R.id.footer_title_1).setText(textModel.footerTitleOne)
view.requireViewById<TextView?>(R.id.footer_title_2).setText(textModel.footerTitleOne)
}
}
}
return view
}
}
private fun setFooterLink(view: View) {
val footerLink: TextView = view.requireViewById(R.id.footer_learn_more)
@@ -185,17 +209,18 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
navigationViewModel.nextStep()
}
val layout: GlifLayout = requireActivity().requireViewById(R.id.setup_wizard_layout)
val layout: GlifLayout = view.findViewById(R.id.setup_wizard_layout)!!
footerBarMixin = layout.getMixin(FooterBarMixin::class.java)
footerBarMixin.primaryButton =
FooterButton.Builder(requireActivity())
FooterButton.Builder(requireContext())
.setText(R.string.security_settings_face_enroll_introduction_more)
.setListener(onNextButtonClick)
.setButtonType(FooterButton.ButtonType.OPT_IN)
.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
.build()
footerBarMixin.setSecondaryButton(
FooterButton.Builder(requireActivity())
FooterButton.Builder(requireContext())
.setText(textModel.negativeButton)
.setListener({ Log.d(TAG, "prevClicked") })
.setButtonType(FooterButton.ButtonType.NEXT)
@@ -211,8 +236,8 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
val requireScrollMixin = layout.getMixin(RequireScrollMixin::class.java)
requireScrollMixin.requireScrollWithButton(
requireActivity(),
footerBarMixin.primaryButton,
requireContext(),
primaryButton,
R.string.security_settings_face_enroll_introduction_more,
onNextButtonClick
)
@@ -224,7 +249,7 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
}
}
lifecycleScope.launch {
viewLifecycleOwner.lifecycleScope.launch {
fingerprintScrollViewModel.hasReadConsentScreen.collect { consented ->
if (consented) {
primaryButton.setText(
@@ -244,7 +269,7 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
// the flow. For instance if someone launches the activity with an invalid challenge, it
// either 1) Fails or 2) Launched confirmDeviceCredential
primaryButton.isEnabled = false
lifecycleScope.launch {
viewLifecycleOwner.lifecycleScope.launch {
gateKeeperViewModel.hasValidGatekeeperInfo.collect { primaryButton.isEnabled = it }
}
}
@@ -284,8 +309,4 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
PorterDuff.Mode.SRC_IN
)
}
private fun getLayout(): GlifLayout? {
return requireView().findViewById(R.id.setup_wizard_layout) as GlifLayout?
}
}

View File

@@ -31,11 +31,6 @@ import kotlinx.coroutines.launch
private const val TAG = "FingerprintEnrollNavigationViewModel"
/** Interface to validate a gatekeeper hat */
interface Validator {
fun validateGateKeeper(challenge: Long?): Boolean
}
/**
* The [EnrollType] for fingerprint enrollment indicates information on how the flow should behave.
*/
@@ -56,7 +51,6 @@ object Unicorn : EnrollType()
*/
class FingerprintEnrollNavigationViewModel(
private val dispatcher: CoroutineDispatcher,
private val validator: Validator,
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
private val canSkipConfirm: Boolean
@@ -145,11 +139,6 @@ class FingerprintEnrollNavigationViewModel(
return FingerprintEnrollNavigationViewModel(
backgroundDispatcher,
object : Validator {
override fun validateGateKeeper(challenge: Long?): Boolean {
return challenge != null
}
},
fingerprintManagerInteractor,
fingerprintGatekeeperViewModel,
canSkipConfirm,

View File

@@ -25,6 +25,8 @@ android_app {
"androidx.fragment_fragment-testing",
"frameworks-base-testutils",
"androidx.fragment_fragment",
"androidx.lifecycle_lifecycle-runtime-testing",
"kotlinx_coroutines_test",
],
aaptflags: ["--extra-packages com.android.settings"],

View File

@@ -0,0 +1,173 @@
/*
* 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.biometrics.fingerprint2.fragment
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.testing.FragmentScenario
import androidx.fragment.app.testing.launchFragmentInContainer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.Visibility
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.runner.AndroidJUnit4
import com.android.settings.R
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollIntroV2Fragment
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollNavigationViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.google.android.setupdesign.GlifLayout
import com.google.android.setupdesign.template.RequireScrollMixin
import kotlinx.coroutines.test.StandardTestDispatcher
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class FingerprintEnrollIntroFragmentTest {
private var context: Context = ApplicationProvider.getApplicationContext()
private var interactor = FakeFingerprintManagerInteractor()
private val gatekeeperViewModel =
FingerprintGatekeeperViewModel(
GatekeeperInfo.GatekeeperPasswordInfo(byteArrayOf(1, 2, 3), 100L),
interactor
)
private val backgroundDispatcher = StandardTestDispatcher()
private lateinit var fragmentScenario: FragmentScenario<FingerprintEnrollIntroV2Fragment>
private val navigationViewModel =
FingerprintEnrollNavigationViewModel(
backgroundDispatcher,
interactor,
gatekeeperViewModel,
canSkipConfirm = true,
)
private var fingerprintViewModel = FingerprintEnrollViewModel(interactor, backgroundDispatcher)
private var fingerprintScrollViewModel = FingerprintScrollViewModel()
@Before
fun setup() {
val factory =
object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(
modelClass: Class<T>,
): T {
return when (modelClass) {
FingerprintEnrollViewModel::class.java -> fingerprintViewModel
FingerprintScrollViewModel::class.java -> fingerprintScrollViewModel
FingerprintEnrollNavigationViewModel::class.java -> navigationViewModel
FingerprintGatekeeperViewModel::class.java -> gatekeeperViewModel
else -> null
}
as T
}
}
fragmentScenario =
launchFragmentInContainer(Bundle(), R.style.SudThemeGlif) {
FingerprintEnrollIntroV2Fragment(factory)
}
}
@Test
fun testScrollToBottomButtonChangesText() {
fragmentScenario.onFragment { fragment ->
onView(withText("I agree")).check(doesNotExist())
val someView = (fragment.requireView().findViewById<GlifLayout>(R.id.setup_wizard_layout))!!
val scrollMixin = someView.getMixin(RequireScrollMixin::class.java)!!
val listener = scrollMixin.onRequireScrollStateChangedListener
// This actually changes the button text
listener.onRequireScrollStateChanged(false)
onView(withText("I agree")).check(matches(isDisplayed()))
}
}
@Test
fun testBasicTitle() {
onView(withText(R.string.security_settings_fingerprint_enroll_introduction_title))
.check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
}
@Test
fun testFooterMessageTwo() {
onView(withId(R.id.footer_message_2))
.check(
matches(
withText(
context.getString(
(R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_2)
)
)
)
)
}
@Test
fun testFooterMessageThree() {
onView(withId(R.id.footer_message_3))
.check(
matches(
withText(
context.getString(
(R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_3)
)
)
)
)
}
@Test
fun testFooterMessageFour() {
onView(withId(R.id.footer_message_4))
.check(
matches(
withText(
context.getString(
(R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_4)
)
)
)
)
}
@Test
fun testFooterMessageFive() {
onView(withId(R.id.footer_message_5))
.check(
matches(
withText(
context.getString(
(R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_5)
)
)
)
)
}
}