Skip to content
This repository was archived by the owner on Aug 21, 2025. It is now read-only.

Commit e1a8824

Browse files
committed
Remove FN and apply N logic
FN: N: First/Last name > Display name NICKNAME: Display name
1 parent 006bbc3 commit e1a8824

File tree

2 files changed

+28
-53
lines changed
  • homeUi/src
    • main/kotlin/com/gravatar/app/homeUi/presentation/home/share/model
    • test/kotlin/com/gravatar/app/homeUi/presentation/home/share/model

2 files changed

+28
-53
lines changed

homeUi/src/main/kotlin/com/gravatar/app/homeUi/presentation/home/share/model/VCard.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,18 @@ internal class VCard private constructor(
1919

2020
val firstName = firstName.orEmpty()
2121
val lastName = lastName.orEmpty()
22-
val nickname = nickname.orEmpty()
2322
if (firstName.isNotEmpty() || lastName.isNotEmpty()) {
2423
contentBuilder.append("N:${lastName.escaped()};${firstName.escaped()};;;\n")
25-
.append(
26-
"FN:${("${firstName.escaped()} ${lastName.escaped()}".trim()).ifEmpty { nickname.escaped() }}\n"
27-
)
24+
} else {
25+
nickname?.takeIf { it.isNotEmpty() }?.let {
26+
contentBuilder.append("N:;${nickname.escaped()};;;\n")
27+
}
2828
}
29-
val calculatedNickname = nickname.ifEmpty { "$firstName $lastName".trim() }.escaped()
3029

31-
calculatedNickname.takeIf { it.isNotEmpty() }?.let { contentBuilder.append("NICKNAME:${it.escaped()}\n") }
30+
nickname?.takeIf { it.isNotEmpty() }?.let {
31+
contentBuilder
32+
.append("NICKNAME:${it.escaped()}\n")
33+
}
3234
organization?.takeIf { it.isNotEmpty() }?.let { contentBuilder.append("ORG:${it.escaped()}\n") }
3335
title?.takeIf { it.isNotEmpty() }?.let { contentBuilder.append("TITLE:${it.escaped()}\n") }
3436
profileUrl?.takeIf { it.isNotEmpty() }?.let { contentBuilder.append("URL:${it.escaped()}\n") }

homeUi/src/test/kotlin/com/gravatar/app/homeUi/presentation/home/share/model/VCardTest.kt

Lines changed: 20 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ class VCardTest {
2626
assertTrue(vCardString.contains("VERSION:3.0"))
2727
assertTrue(vCardString.contains("PRODID:Gravatar Android"))
2828
assertTrue(vCardString.contains("N:Doe;John;;;"))
29-
assertTrue(vCardString.contains("FN:John Doe"))
3029
assertTrue(vCardString.contains("NICKNAME:Johnny"))
3130
assertTrue(vCardString.contains("ORG:Gravatar"))
3231
assertTrue(vCardString.contains("TITLE:Developer"))
@@ -51,8 +50,6 @@ class VCardTest {
5150
assertTrue(vCardString.contains("VERSION:3.0"))
5251
assertTrue(vCardString.contains("PRODID:Gravatar Android"))
5352
assertTrue(vCardString.contains("N:;Jane;;;")) // Last name is empty
54-
assertTrue(vCardString.contains("FN:Jane")) // FN falls back to first name
55-
assertTrue(vCardString.contains("NICKNAME:Jane")) // Nickname falls back to FN
5653
assertTrue(vCardString.contains("ORG:Automattic"))
5754
assertTrue(vCardString.contains("EMAIL:jane.doe@example.com"))
5855
assertTrue(vCardString.endsWith("END:VCARD"))
@@ -78,49 +75,6 @@ class VCardTest {
7875
)
7976
}
8077

81-
@Test
82-
fun `FN and NICKNAME fall back correctly when names or nickname are empty`() {
83-
// Case 1: Only first name
84-
var vCard = VCard.Builder().firstName("Solo").build()
85-
var vCardString = vCard.toString()
86-
assertTrue(vCardString.contains("N:;Solo;;;"))
87-
assertTrue(vCardString.contains("FN:Solo"))
88-
assertTrue(vCardString.contains("NICKNAME:Solo"))
89-
90-
// Case 2: Only last name
91-
vCard = VCard.Builder().lastName("OnlyLastName").build()
92-
vCardString = vCard.toString()
93-
assertTrue(vCardString.contains("N:OnlyLastName;;;;"))
94-
assertTrue(vCardString.contains("FN:OnlyLastName"))
95-
assertTrue(vCardString.contains("NICKNAME:OnlyLastName"))
96-
97-
// Case 3: First name, last name, but empty nickname
98-
vCard = VCard.Builder().firstName("First").lastName("Last").nickname("").build()
99-
vCardString = vCard.toString()
100-
assertTrue(vCardString.contains("N:Last;First;;;"))
101-
assertTrue(vCardString.contains("FN:First Last"))
102-
assertTrue(vCardString.contains("NICKNAME:First Last")) // Falls back to FN
103-
104-
// Case 4: Only nickname
105-
vCard = VCard.Builder().nickname("JustNickname").build()
106-
vCardString = vCard.toString()
107-
assertEquals(
108-
"BEGIN:VCARD\n" +
109-
"VERSION:3.0\n" +
110-
"PRODID:Gravatar Android\n" +
111-
"NICKNAME:JustNickname\n" +
112-
"END:VCARD",
113-
vCardString
114-
)
115-
116-
// Case 5: First name, last name, and nickname (nickname should take precedence for NICKNAME field)
117-
vCard = VCard.Builder().firstName("Official").lastName("Name").nickname("PreferredNick").build()
118-
vCardString = vCard.toString()
119-
assertTrue(vCardString.contains("N:Name;Official;;;"))
120-
assertTrue(vCardString.contains("FN:Official Name"))
121-
assertTrue(vCardString.contains("NICKNAME:PreferredNick"))
122-
}
123-
12478
@Test
12579
fun `builder handles null inputs gracefully`() {
12680
val vCard = VCard.Builder()
@@ -186,7 +140,6 @@ class VCardTest {
186140
val vCardString = vCard.toString()
187141

188142
assertTrue(vCardString.contains("N:Last Name;First Name;;;"))
189-
assertTrue(vCardString.contains("FN:First Name Last Name"))
190143
assertTrue(vCardString.contains("NICKNAME:Nick Name"))
191144
assertTrue(vCardString.contains("ORG:Org Name"))
192145
assertTrue(vCardString.contains("TITLE:Job Title"))
@@ -195,4 +148,24 @@ class VCardTest {
195148
assertTrue(vCardString.contains("TEL;TYPE=cell:123 456 7890"))
196149
assertTrue(vCardString.contains("EMAIL:user name@example.com"))
197150
}
151+
152+
@Test
153+
fun `when no firstName and lastName but nickname exists, N field uses nickname`() {
154+
val vCard = VCard.Builder()
155+
.nickname("JohnDoe")
156+
.organization("Gravatar")
157+
.email("john.doe@example.com")
158+
.build()
159+
160+
val vCardString = vCard.toString()
161+
162+
assertTrue(vCardString.contains("BEGIN:VCARD"))
163+
assertTrue(vCardString.contains("VERSION:3.0"))
164+
assertTrue(vCardString.contains("PRODID:Gravatar Android"))
165+
assertTrue(vCardString.contains("N:;JohnDoe;;;")) // N field should use nickname
166+
assertTrue(vCardString.contains("NICKNAME:JohnDoe"))
167+
assertTrue(vCardString.contains("ORG:Gravatar"))
168+
assertTrue(vCardString.contains("EMAIL:john.doe@example.com"))
169+
assertTrue(vCardString.endsWith("END:VCARD"))
170+
}
198171
}

0 commit comments

Comments
 (0)