[fenix] for https://github.com/mozilla-mobile/fenix/issues/24931: create address label and description based on available data

pull/600/head
MatthewTighe 2 years ago committed by mergify[bot]
parent 05d51d4bcb
commit a5643471f2

@ -41,6 +41,7 @@ private val ICON_SIZE = 24.dp
* @param label The label in the list item.
* @param modifier [Modifier] to be applied to the layout.
* @param description An optional description text below the label.
* @param maxDescriptionLines An optional maximum number of lines for the description text to span.
* @param onClick Called when the user clicks on the item.
* @param iconPainter [Painter] used to display a [ListItemIcon] after the list item.
* @param iconDescription Content description of the icon.
@ -51,6 +52,7 @@ fun TextListItem(
label: String,
modifier: Modifier = Modifier,
description: String? = null,
maxDescriptionLines: Int = 1,
onClick: (() -> Unit)? = null,
iconPainter: Painter? = null,
iconDescription: String? = null,
@ -60,6 +62,7 @@ fun TextListItem(
label = label,
modifier = modifier,
description = description,
maxDescriptionLines = maxDescriptionLines,
onClick = onClick,
afterListAction = {
iconPainter?.let {
@ -172,6 +175,7 @@ fun IconListItem(
* @param label The label in the list item.
* @param modifier [Modifier] to be applied to the layout.
* @param description An optional description text below the label.
* @param maxDescriptionLines An optional maximum number of lines for the description text to span.
* @param onClick Called when the user clicks on the item.
* @param beforeListAction Optional Composable for adding UI before the list item.
* @param afterListAction Optional Composable for adding UI to the end of the list item.
@ -181,6 +185,7 @@ private fun ListItem(
label: String,
modifier: Modifier = Modifier,
description: String? = null,
maxDescriptionLines: Int = 1,
onClick: (() -> Unit)? = null,
beforeListAction: @Composable RowScope.() -> Unit = {},
afterListAction: @Composable RowScope.() -> Unit = {},
@ -211,7 +216,7 @@ private fun ListItem(
SecondaryText(
text = description,
fontSize = 14.sp,
maxLines = 1,
maxLines = maxDescriptionLines,
)
}
}

@ -0,0 +1,38 @@
/* 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.settings.address.ext
import androidx.annotation.VisibleForTesting
import mozilla.components.concept.storage.Address
/**
* Generate a label item text for an [Address]. The combination of names is based on desktop code
* found here:
* https://searchfox.org/mozilla-central/rev/d989c65584ded72c2de85cb40bede7ac2f176387/toolkit/components/formautofill/FormAutofillNameUtils.jsm#400
*/
fun Address.getFullName(): String = listOf(givenName, additionalName, familyName)
.filter { it.isNotEmpty() }
.joinToString(" ")
/**
* Generate a description item text for an [Address]. The element ordering is based on the
* priorities defined by the desktop code found here:
* https://searchfox.org/mozilla-central/rev/d989c65584ded72c2de85cb40bede7ac2f176387/toolkit/components/formautofill/FormAutofillUtils.jsm#323
*/
fun Address.getAddressLabel(): String = listOf(
streetAddress.toOneLineAddress(),
addressLevel3,
addressLevel2,
organization,
addressLevel1,
country,
postalCode,
tel,
email
).filter { it.isNotEmpty() }.joinToString(", ")
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
internal fun String.toOneLineAddress(): String =
this.split("\n").joinToString(separator = " ") { it.trim() }

@ -19,6 +19,8 @@ import mozilla.components.concept.storage.Address
import org.mozilla.fenix.R
import org.mozilla.fenix.compose.list.IconListItem
import org.mozilla.fenix.compose.list.TextListItem
import org.mozilla.fenix.settings.address.ext.getAddressLabel
import org.mozilla.fenix.settings.address.ext.getFullName
import org.mozilla.fenix.theme.FirefoxTheme
import org.mozilla.fenix.theme.Theme
@ -38,9 +40,10 @@ fun AddressList(
LazyColumn {
items(addresses) { address ->
TextListItem(
label = address.givenName + " " + address.familyName,
label = address.getFullName(),
modifier = Modifier.padding(start = 56.dp),
description = address.streetAddress,
description = address.getAddressLabel(),
maxDescriptionLines = 2,
onClick = { onAddressClick(address) },
)
}

@ -0,0 +1,143 @@
/* 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.settings.address.ext
import mozilla.components.concept.storage.Address
import org.junit.Assert.assertEquals
import org.junit.Test
class AddressTest {
@Test
fun `WHEN all names are populated THEN label includes all names`() {
val addr = generateAddress()
val label = addr.getFullName()
assertEquals("${addr.givenName} ${addr.additionalName} ${addr.familyName}", label)
}
@Test
fun `WHEN middle name is missing THEN label is given and family combined`() {
val addr = generateAddress(additionalName = "")
val label = addr.getFullName()
assertEquals("${addr.givenName} ${addr.familyName}", label)
}
@Test
fun `WHEN only family and middle name are available THEN label is middle and family combined`() {
val addr = generateAddress(givenName = "")
val label = addr.getFullName()
assertEquals("${addr.additionalName} ${addr.familyName}", label)
}
@Test
fun `WHEN only family name is available THEN label is family name`() {
val addr = generateAddress(givenName = "", additionalName = "")
val label = addr.getFullName()
assertEquals(addr.familyName, label)
}
@Test
fun `WHEN all properties are present THEN all properties present in description`() {
val addr = generateAddress()
val description = addr.getAddressLabel()
val expected = "${addr.streetAddress}, ${addr.addressLevel3}, ${addr.addressLevel2}, " +
"${addr.organization}, ${addr.addressLevel1}, ${addr.country}, " +
"${addr.postalCode}, ${addr.tel}, ${addr.email}"
assertEquals(expected, description)
}
@Test
fun `WHEN any properties are missing THEN description includes only present`() {
val addr = generateAddress(
addressLevel3 = "",
organization = "",
email = "",
)
val description = addr.getAddressLabel()
val expected = "${addr.streetAddress}, ${addr.addressLevel2}, ${addr.addressLevel1}, " +
"${addr.country}, ${addr.postalCode}, ${addr.tel}"
assertEquals(expected, description)
}
@Test
fun `WHEN everything is missing THEN description is empty`() {
val addr = generateAddress(
givenName = "",
additionalName = "",
familyName = "",
organization = "",
streetAddress = "",
addressLevel3 = "",
addressLevel2 = "",
addressLevel1 = "",
postalCode = "",
country = "",
tel = "",
email = ""
)
val description = addr.getAddressLabel()
assertEquals("", description)
}
@Test
fun `GIVEN multiline street address THEN joined as single line`() {
val streetAddress = """
line1
line2
line3
""".trimIndent()
val result = streetAddress.toOneLineAddress()
assertEquals("line1 line2 line3", result)
}
private fun generateAddress(
givenName: String = "Firefox",
additionalName: String = "The",
familyName: String = "Browser",
organization: String = "Mozilla",
streetAddress: String = "street",
addressLevel3: String = "3",
addressLevel2: String = "2",
addressLevel1: String = "1",
postalCode: String = "code",
country: String = "country",
tel: String = "tel",
email: String = "email",
) = Address(
guid = "",
givenName = givenName,
additionalName = additionalName,
familyName = familyName,
organization = organization,
streetAddress = streetAddress,
addressLevel3 = addressLevel3,
addressLevel2 = addressLevel2,
addressLevel1 = addressLevel1,
postalCode = postalCode,
country = country,
tel = tel,
email = email,
timeCreated = 1,
timeLastUsed = 1,
timeLastModified = 1,
timesUsed = 1,
)
}
Loading…
Cancel
Save