1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.messenger.common; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.text.BidiFormatter; 22 23 import androidx.test.ext.junit.runners.AndroidJUnit4; 24 25 import org.junit.Test; 26 import org.junit.runner.RunWith; 27 28 import java.util.Arrays; 29 import java.util.List; 30 31 @RunWith(AndroidJUnit4.class) 32 public class UtilsTest { 33 34 private static final String ARABIC_NAME = "جﺗﺧ"; 35 private static final List<String> NAMES = Arrays.asList("+1-650-900-1234", "Logan.", "Emily", 36 "Christopher", "!Sam", ARABIC_NAME); 37 private static final String NAME_DELIMITER = "، "; 38 private static final String TITLE_DELIMITER = " : "; 39 private static final int TITLE_LENGTH = 30; 40 private static final BidiFormatter RTL_FORMATTER = BidiFormatter.getInstance(/* rtlContext= */ 41 true); 42 43 @Test testNameWithMultipleNumbers()44 public void testNameWithMultipleNumbers() { 45 // Ensure that a group name with many phone numbers sorts the phone numbers correctly. 46 List<String> senderNames = Arrays.asList("+1-650-900-1234", "+1-650-900-1111", 47 "+1-100-200-1234"); 48 String actual = Utils.constructGroupConversationTitle(senderNames, NAME_DELIMITER, 49 TITLE_LENGTH + 20); 50 String expected = "+1-100-200-1234، +1-650-900-1111، +1-650-900-1234"; 51 assertThat(actual).isEqualTo(expected); 52 } 53 54 @Test testNameWithInternationalNumbers()55 public void testNameWithInternationalNumbers() { 56 // Ensure that a group name with many phone numbers sorts the phone numbers correctly. 57 List<String> senderNames = Arrays.asList("+44-20-7183-8750", "+1-650-900-1111", 58 "+1-100-200-1234"); 59 String actual = Utils.constructGroupConversationTitle(senderNames, NAME_DELIMITER, 60 TITLE_LENGTH + 20); 61 String expected = "+1-100-200-1234، +1-650-900-1111، +44-20-7183-8750"; 62 assertThat(actual).isEqualTo(expected); 63 } 64 65 @Test testNameConstructorLtr()66 public void testNameConstructorLtr() { 67 String actual = Utils.constructGroupConversationTitle(NAMES, NAME_DELIMITER, TITLE_LENGTH); 68 assertThat(actual).isEqualTo("!Sam، Christopher، Emily، Logan."); 69 } 70 71 @Test testNameConstructorLtr_longerTitle()72 public void testNameConstructorLtr_longerTitle() { 73 String actual = Utils.constructGroupConversationTitle(NAMES, NAME_DELIMITER, 74 TITLE_LENGTH + 5); 75 assertThat(actual).isEqualTo( 76 "!Sam، Christopher، Emily، Logan.، \u200E\u202Bجﺗﺧ\u202C\u200E"); 77 78 } 79 80 @Test testTitleConstructorLtr()81 public void testTitleConstructorLtr() { 82 String actual = Utils.constructGroupConversationHeader("Christopher", 83 "!Sam، Emily، Logan.، +1-650-900-1234", TITLE_DELIMITER); 84 String expected = "Christopher : !Sam، Emily، Logan.، +1-650-900-1234"; 85 assertThat(actual).isEqualTo(expected); 86 } 87 88 @Test testTitleConstructorLtr_with_rtlName()89 public void testTitleConstructorLtr_with_rtlName() { 90 String actual = Utils.constructGroupConversationHeader(ARABIC_NAME, "!Sam، Logan.، جﺗﺧ", 91 TITLE_DELIMITER); 92 // Note: the Group name doesn't have the RTL tag because in the function we format the 93 // entire group name string, not each name in the string. 94 String expected = "\u200E\u202Bجﺗﺧ\u202C\u200E : !Sam، Logan.، جﺗﺧ\u200E"; 95 assertThat(actual).isEqualTo(expected); 96 } 97 98 @Test testTitleConstructorLtr_with_phoneNumber()99 public void testTitleConstructorLtr_with_phoneNumber() { 100 String actual = Utils.constructGroupConversationHeader("+1-650-900-1234", 101 "!Sam، Logan.، جﺗﺧ", 102 TITLE_DELIMITER); 103 // Note: the Group name doesn't have the RTL tag because in the function we format the 104 // entire group name string, not each name in the string. 105 String expected = "+1-650-900-1234 : !Sam، Logan.، جﺗﺧ\u200E"; 106 assertThat(actual).isEqualTo(expected); 107 } 108 109 /** 110 * NOTE for all the RTL tests done below: When BidiFormatter is unicode-wrapping strings, they 111 * are actually adding invisible Unicode characters to denote whether a section is RTL, LTR, 112 * etc. These invisible characters are NOT visible on the terminal output, or if you copy 113 * paste the string to most HTML pages. They ARE visible when you paste them in certain 114 * text editors like IntelliJ, or there are some online tools that provide this as well. 115 * 116 * Therefore, in most of these RTL tests (and some of the LTR tests) you will see the 117 * invisible characters in the expected strings. Here's a couple of the characters, and what 118 * they're used for: 119 * \u200F is the RTL mark 120 * \u200E is the LTR mark 121 * \u202A marks the start of LTR embedding 122 * \u202B marks the start of RTL embedding 123 * \u202C pops the directional formatting - Must be used to end an embedding 124 */ 125 @Test testNameWithInternationalNumbers_rtl()126 public void testNameWithInternationalNumbers_rtl() { 127 // Ensure that a group name with many phone numbers sorts the phone numbers correctly. 128 List<String> senderNames = Arrays.asList("+44-20-7183-8750", "+1-650-900-1111", 129 "+1-100-200-1234"); 130 String actual = Utils.constructGroupConversationTitle(senderNames, NAME_DELIMITER, 131 TITLE_LENGTH + 20, RTL_FORMATTER); 132 String expected = "\u200F\u202A\u200F\u202A+1-100-200-1234\u202C\u200F\u200F\u202A، " 133 + "\u202C\u200F\u200F\u202A+1-650-900-1111\u202C\u200F\u200F\u202A، " 134 + "\u202C\u200F\u200F\u202A+44-20-7183-8750\u202C\u200F\u202C\u200F"; 135 assertThat(actual).isEqualTo(expected); 136 } 137 138 @Test testNameConstructorRtl()139 public void testNameConstructorRtl() { 140 String actual = Utils.constructGroupConversationTitle(NAMES, NAME_DELIMITER, TITLE_LENGTH, 141 /* isRtl */ RTL_FORMATTER); 142 143 String expected = 144 "\u200F\u202A\u200F\u202A!Sam\u202C\u200F\u200F\u202A، \u202C\u200F" 145 + "\u200F\u202AChristopher\u202C\u200F\u200F\u202A، \u202C\u200F" 146 + "\u200F\u202AEmily\u202C\u200F\u200F\u202A، " 147 + "\u202C\u200F\u200F\u202ALogan.\u202C\u200F\u202C\u200F"; 148 assertThat(actual).isEqualTo(expected); 149 } 150 151 @Test testNameConstructorRtl_longerTitle()152 public void testNameConstructorRtl_longerTitle() { 153 String actual = Utils.constructGroupConversationTitle(NAMES, NAME_DELIMITER, 154 TITLE_LENGTH + 5, /* isRtl */ RTL_FORMATTER); 155 156 String expected = 157 "\u200F\u202A\u200F\u202A!Sam\u202C\u200F\u200F\u202A، " 158 + "\u202C\u200F\u200F\u202AChristopher\u202C\u200F\u200F" 159 + "\u202A، \u202C\u200F\u200F\u202AEmily\u202C\u200F\u200F\u202A، " 160 + "\u202C\u200F\u200F\u202ALogan.\u202C\u200F\u200F\u202A، " 161 + "\u202C\u200Fجﺗﺧ\u202C\u200F"; 162 assertThat(actual).isEqualTo(expected); 163 } 164 165 @Test testTitleConstructorRtl_with_rtlName()166 public void testTitleConstructorRtl_with_rtlName() { 167 String actual = Utils.constructGroupConversationHeader(ARABIC_NAME, "!Sam، Logan.، جﺗﺧ", 168 TITLE_DELIMITER, RTL_FORMATTER); 169 // Note: the Group name doesn't have the RTL tag because in the function we format the 170 // entire group name string, not each name in the string. 171 // Also, note that the sender's name, which is RTL still has LTR embedded because we wrap 172 // it with FIRSTSTRONG_LTR. 173 String expected = "\u200F\u202Aجﺗﺧ : \u200F\u202A!Sam، Logan.، جﺗﺧ\u202C\u200F\u202C" 174 + "\u200F"; 175 assertThat(actual).isEqualTo(expected); 176 } 177 178 179 @Test testTitleConstructorRtl_with_phoneNumber()180 public void testTitleConstructorRtl_with_phoneNumber() { 181 String actual = Utils.constructGroupConversationHeader("+1-650-900-1234", 182 "!Sam، Logan.، جﺗﺧ", 183 TITLE_DELIMITER, RTL_FORMATTER); 184 // Note: the Group name doesn't have the RTL tag because in the function we format the 185 // entire group name string, not each name in the string. 186 String expected = "\u200F\u202A\u200F\u202A+1-650-900-1234\u202C\u200F : " 187 + "\u200F\u202A!Sam، Logan.، جﺗﺧ\u202C\u200F\u202C\u200F"; 188 assertThat(actual).isEqualTo(expected); 189 } 190 191 @Test testTitleConstructorRtl()192 public void testTitleConstructorRtl() { 193 String actual = Utils.constructGroupConversationHeader("Christopher", 194 "+1-650-900-1234، Logan.، Emily، Christopher، !Sam", TITLE_DELIMITER, /* isRtl */ 195 RTL_FORMATTER).trim(); 196 197 String expected = 198 "\u200F\u202A\u200F\u202AChristopher\u202C\u200F : \u200F\u202A+1-650-900-1234، " 199 + "Logan.، Emily، Christopher، !Sam\u202C\u200F\u202C\u200F"; 200 201 assertThat(actual).isEqualTo(expected); 202 } 203 204 @Test testTitleConstructorRtl_withTrailingPunctuation()205 public void testTitleConstructorRtl_withTrailingPunctuation() { 206 String actual = Utils.constructGroupConversationHeader("Christopher", 207 "Abcd!!!", TITLE_DELIMITER, /* isRtl */ 208 RTL_FORMATTER).trim(); 209 210 String expected = 211 "\u200F\u202A\u200F\u202AChristopher\u202C\u200F : \u200F\u202AAbcd!!!" 212 + "\u202C\u200F\u202C\u200F"; 213 214 assertThat(actual).isEqualTo(expected); 215 } 216 } 217