BIT-2180: Check htmlInfo for username field (#1318)

This commit is contained in:
David Perez 2024-04-29 16:01:28 -05:00 committed by Álison Fernandes
parent 5a6e3254ea
commit b8fdadcedb
4 changed files with 51 additions and 6 deletions

View file

@ -41,14 +41,20 @@ class SaveInfoBuilderImpl(
return if (autofillPartition is AutofillPartition.Login && isInCompatMode) {
null
} else {
val saveInfoBuilder = SaveInfo
SaveInfo
.Builder(
autofillPartition.saveType,
autofillPartition.requiredSaveIds.toTypedArray(),
)
.setOptionalIds(autofillPartition.optionalSaveIds.toTypedArray())
if (isInCompatMode) saveInfoBuilder.setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
saveInfoBuilder.build()
.apply {
// setOptionalIds will throw an IllegalArgumentException if the array is empty
autofillPartition
.optionalSaveIds
.takeUnless { it.isEmpty() }
?.let { setOptionalIds(it.toTypedArray()) }
if (isInCompatMode) setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
}
.build()
}
}
}

View file

@ -25,6 +25,28 @@ fun HtmlInfo?.isPasswordField(): Boolean =
}
?: false
/**
* Whether this [HtmlInfo] represents a username field.
*
* This function is untestable as [HtmlInfo] contains [android.util.Pair] which requires
* instrumentation testing.
*/
@OmitFromCoverage
fun HtmlInfo?.isUsernameField(): Boolean =
this
?.let { htmlInfo ->
if (htmlInfo.isInputField) {
htmlInfo
.attributes
?.any {
it.first == "type" && it.second == "email"
}
} else {
false
}
}
?: false
/**
* Whether this [HtmlInfo] represents an input field.
*/

View file

@ -183,7 +183,8 @@ fun AssistStructure.ViewNode.isUsernameField(
supportedHint == View.AUTOFILL_HINT_EMAIL_ADDRESS ||
inputType.isUsernameInputType ||
idEntry?.containsAnyTerms(SUPPORTED_RAW_USERNAME_HINTS) == true ||
hint?.containsAnyTerms(SUPPORTED_RAW_USERNAME_HINTS) == true
hint?.containsAnyTerms(SUPPORTED_RAW_USERNAME_HINTS) == true ||
htmlInfo.isUsernameField()
/**
* The website that this [AssistStructure.ViewNode] is a part of representing.

View file

@ -356,7 +356,7 @@ class ViewNodeExtensionsTest {
}
@Test
fun `isUsernameField returns true whe supportedHint is AUTOFILL_HINT_USERNAME`() {
fun `isUsernameField returns true when supportedHint is AUTOFILL_HINT_USERNAME`() {
// Setup
val supportedHint = View.AUTOFILL_HINT_USERNAME
@ -416,6 +416,21 @@ class ViewNodeExtensionsTest {
}
}
@Test
fun `isUsernameField returns true when htmlInfo isUserNameField is true`() {
every { viewNode.idEntry } returns null
every { viewNode.hint } returns null
every { viewNode.htmlInfo.isUsernameField() } returns true
// Test
val actual = viewNode.isUsernameField(
supportedHint = null,
)
// Verify
assertTrue(actual)
}
@Test
fun `website should return URI if domain and scheme are valid`() {
// Setup
@ -496,6 +511,7 @@ class ViewNodeExtensionsTest {
private fun setupUnsupportedInputFieldViewNode() {
every { viewNode.hint } returns null
every { viewNode.htmlInfo.isPasswordField() } returns false
every { viewNode.htmlInfo.isUsernameField() } returns false
every { viewNode.htmlInfo.isInputField } returns true
every { viewNode.idEntry } returns null
every { viewNode.autofillHints } returns emptyArray()