1/*
2 * Copyright (C) 2008 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 */
16package com.android.internal.telephony;
17
18import android.telephony.PhoneNumberFormattingTextWatcher;
19import android.test.AndroidTestCase;
20import android.text.Editable;
21import android.text.Selection;
22import android.text.SpannableStringBuilder;
23import android.text.TextWatcher;
24
25public class PhoneNumberWatcherTest extends AndroidTestCase {
26    public void testAppendChars() {
27        final String multiChars = "65012345";
28        final String formatted1 = "(650) 123-45";
29        TextWatcher textWatcher = getTextWatcher();
30        SpannableStringBuilder number = new SpannableStringBuilder();
31        // Append more than one chars
32        textWatcher.beforeTextChanged(number, 0, 0, multiChars.length());
33        number.append(multiChars);
34        Selection.setSelection(number, number.length());
35        textWatcher.onTextChanged(number, 0, 0, number.length());
36        textWatcher.afterTextChanged(number);
37        assertEquals(formatted1, number.toString());
38        assertEquals(formatted1.length(), Selection.getSelectionEnd(number));
39        // Append one chars
40        final char appendChar = '6';
41        final String formatted2 = "(650) 123-456";
42        int len = number.length();
43        textWatcher.beforeTextChanged(number, number.length(), 0, 1);
44        number.append(appendChar);
45        Selection.setSelection(number, number.length());
46        textWatcher.onTextChanged(number, len, 0, 1);
47        textWatcher.afterTextChanged(number);
48        assertEquals(formatted2, number.toString());
49        assertEquals(formatted2.length(), Selection.getSelectionEnd(number));
50    }
51
52    public void testRemoveLastChars() {
53        final String init = "65012345678";
54        final String result1 = "(650) 123-4567";
55        TextWatcher textWatcher = getTextWatcher();
56        // Remove the last char.
57        SpannableStringBuilder number = new SpannableStringBuilder(init);
58        int len = number.length();
59        textWatcher.beforeTextChanged(number, len - 1, 1, 0);
60        number.delete(len - 1, len);
61        Selection.setSelection(number, number.length());
62        textWatcher.onTextChanged(number, number.length() - 1, 1, 0);
63        textWatcher.afterTextChanged(number);
64        assertEquals(result1, number.toString());
65        assertEquals(result1.length(), Selection.getSelectionEnd(number));
66        // Remove last 5 chars
67        final String result2 = "650-123";
68        textWatcher.beforeTextChanged(number, number.length() - 4, 4, 0);
69        number.delete(number.length() - 5, number.length());
70        Selection.setSelection(number, number.length());
71        textWatcher.onTextChanged(number, number.length(), 4, 0);
72        textWatcher.afterTextChanged(number);
73        assertEquals(result2, number.toString());
74        assertEquals(result2.length(), Selection.getSelectionEnd(number));
75    }
76
77    public void testInsertChars() {
78        final String init = "650-23";
79        final String expected1 = "650-123";
80        TextWatcher textWatcher = getTextWatcher();
81
82        // Insert one char
83        SpannableStringBuilder number = new SpannableStringBuilder(init);
84        textWatcher.beforeTextChanged(number, 3, 0, 1);
85        number.insert(3, "1"); // 6501-23
86        Selection.setSelection(number, 4); // make the cursor at right of 1
87        textWatcher.onTextChanged(number, 3, 0, 1);
88        textWatcher.afterTextChanged(number);
89        assertEquals(expected1, number.toString());
90        // the cursor should still at the right of '1'
91        assertEquals(5, Selection.getSelectionEnd(number));
92
93        // Insert multiple chars
94        final String expected2 = "(650) 145-6723";
95        textWatcher.beforeTextChanged(number, 5, 0, 4);
96        number.insert(5, "4567"); // change to 650-1456723
97        Selection.setSelection(number, 9); // the cursor is at the right of '7'.
98        textWatcher.onTextChanged(number, 7, 0, 4);
99        textWatcher.afterTextChanged(number);
100        assertEquals(expected2, number.toString());
101        // the cursor should be still at the right of '7'
102        assertEquals(12, Selection.getSelectionEnd(number));
103    }
104
105    public void testStopFormatting() {
106        final String init = "(650) 123";
107        final String expected1 = "(650) 123 4";
108        TextWatcher textWatcher = getTextWatcher();
109
110        // Append space
111        SpannableStringBuilder number = new SpannableStringBuilder(init);
112        textWatcher.beforeTextChanged(number, 9, 0, 2);
113        number.insert(9, " 4"); // (6501) 23 4
114        Selection.setSelection(number, number.length()); // make the cursor at right of 4
115        textWatcher.onTextChanged(number, 9, 0, 2);
116        textWatcher.afterTextChanged(number);
117        assertEquals(expected1, number.toString());
118        // the cursor should still at the right of '1'
119        assertEquals(expected1.length(), Selection.getSelectionEnd(number));
120
121        // Delete a ')'
122        final String expected2 ="(650 123";
123        textWatcher = getTextWatcher();
124        number = new SpannableStringBuilder(init);
125        textWatcher.beforeTextChanged(number, 4, 1, 0);
126        number.delete(4, 5); // (6501 23 4
127        Selection.setSelection(number, 5); // make the cursor at right of 1
128        textWatcher.onTextChanged(number, 4, 1, 0);
129        textWatcher.afterTextChanged(number);
130        assertEquals(expected2, number.toString());
131        // the cursor should still at the right of '1'
132        assertEquals(5, Selection.getSelectionEnd(number));
133
134        // Insert a hyphen
135        final String expected3 ="(650) 12-3";
136        textWatcher = getTextWatcher();
137        number = new SpannableStringBuilder(init);
138        textWatcher.beforeTextChanged(number, 8, 0, 1);
139        number.insert(8, "-"); // (650) 12-3
140        Selection.setSelection(number, 9); // make the cursor at right of -
141        textWatcher.onTextChanged(number, 8, 0, 1);
142        textWatcher.afterTextChanged(number);
143        assertEquals(expected3, number.toString());
144        // the cursor should still at the right of '-'
145        assertEquals(9, Selection.getSelectionEnd(number));
146    }
147
148    public void testRestartFormatting() {
149        final String init = "(650) 123";
150        final String expected1 = "(650) 123 4";
151        TextWatcher textWatcher = getTextWatcher();
152
153        // Append space
154        SpannableStringBuilder number = new SpannableStringBuilder(init);
155        textWatcher.beforeTextChanged(number, 9, 0, 2);
156        number.insert(9, " 4"); // (650) 123 4
157        Selection.setSelection(number, number.length()); // make the cursor at right of 4
158        textWatcher.onTextChanged(number, 9, 0, 2);
159        textWatcher.afterTextChanged(number);
160        assertEquals(expected1, number.toString());
161        // the cursor should still at the right of '4'
162        assertEquals(expected1.length(), Selection.getSelectionEnd(number));
163
164        // Clear the current string, and start formatting again.
165        int len = number.length();
166        textWatcher.beforeTextChanged(number, 0, len, 0);
167        number.delete(0, len);
168        textWatcher.onTextChanged(number, 0, len, 0);
169        textWatcher.afterTextChanged(number);
170
171        final String expected2 = "650-1234";
172        number = new SpannableStringBuilder(init);
173        textWatcher.beforeTextChanged(number, 9, 0, 1);
174        number.insert(9, "4"); // (650) 1234
175        Selection.setSelection(number, number.length()); // make the cursor at right of 4
176        textWatcher.onTextChanged(number, 9, 0, 1);
177        textWatcher.afterTextChanged(number);
178        assertEquals(expected2, number.toString());
179        // the cursor should still at the right of '4'
180        assertEquals(expected2.length(), Selection.getSelectionEnd(number));
181    }
182
183    public void testTextChangedByOtherTextWatcher() {
184        final TextWatcher cleanupTextWatcher = new TextWatcher() {
185            @Override
186            public void afterTextChanged(Editable s) {
187                s.clear();
188            }
189
190            @Override
191            public void beforeTextChanged(CharSequence s, int start, int count,
192                    int after) {
193            }
194
195            @Override
196            public void onTextChanged(CharSequence s, int start, int before,
197                    int count) {
198            }
199        };
200        final String init = "(650) 123";
201        final String expected1 = "";
202        TextWatcher textWatcher = getTextWatcher();
203
204        SpannableStringBuilder number = new SpannableStringBuilder(init);
205        textWatcher.beforeTextChanged(number, 5, 0, 1);
206        number.insert(5, "4"); // (6504) 123
207        Selection.setSelection(number, 5); // make the cursor at right of 4
208        textWatcher.onTextChanged(number, 5, 0, 1);
209        number.setSpan(cleanupTextWatcher, 0, number.length(), 0);
210        textWatcher.afterTextChanged(number);
211        assertEquals(expected1, number.toString());
212    }
213
214    /**
215     * Test the case where some other component is auto-completing what the user is typing
216     */
217    public void testAutoCompleteWithFormattedNumber() {
218        String init = "650-1";
219        String expected = "+1-650-123-4567"; // Different formatting than ours
220        testReplacement(init, expected, expected);
221    }
222
223    /**
224     * Test the case where some other component is auto-completing what the user is typing
225     */
226    public void testAutoCompleteWithFormattedNameAndNumber() {
227        String init = "650-1";
228        String expected = "Test User <650-123-4567>";
229        testReplacement(init, expected, expected);
230    }
231
232    /**
233     * Test the case where some other component is auto-completing what the user is typing
234     */
235    public void testAutoCompleteWithNumericNameAndNumber() {
236        String init = "650";
237        String expected = "2nd Test User <650-123-4567>";
238        testReplacement(init, expected, expected);
239    }
240
241    /**
242     * Test the case where some other component is auto-completing what the user is typing
243     */
244    public void testAutoCompleteWithUnformattedNumber() {
245        String init = "650-1";
246        String expected = "6501234567";
247        testReplacement(init, expected, expected);
248    }
249
250    /**
251     * Test the case where some other component is auto-completing what the user is typing, where
252     * the deleted text doesn't have any formatting and neither does the replacement text: in this
253     * case the replacement text should be formatted by the PhoneNumberFormattingTextWatcher.
254     */
255    public void testAutoCompleteUnformattedWithUnformattedNumber() {
256        String init = "650";
257        String replacement = "6501234567";
258        String expected = "(650) 123-4567";
259        testReplacement(init, replacement, expected);
260
261        String init2 = "650";
262        String replacement2 = "16501234567";
263        String expected2 = "1 650-123-4567";
264        testReplacement(init2, replacement2, expected2);
265    }
266
267    /**
268     * Helper method for testing replacing the entire string with another string
269     * @param init The initial string
270     * @param expected
271     */
272    private void testReplacement(String init, String replacement, String expected) {
273        TextWatcher textWatcher = getTextWatcher();
274
275        SpannableStringBuilder number = new SpannableStringBuilder(init);
276
277        // Replace entire text with the given values
278        textWatcher.beforeTextChanged(number, 0, init.length(), replacement.length());
279        number.replace(0, init.length(), replacement, 0, replacement.length());
280        Selection.setSelection(number, replacement.length()); // move the cursor to the end
281        textWatcher.onTextChanged(number, 0, init.length(), replacement.length());
282        textWatcher.afterTextChanged(number);
283
284        assertEquals(expected, number.toString());
285        // the cursor should be still at the end
286        assertEquals(expected.length(), Selection.getSelectionEnd(number));
287    }
288
289    private TextWatcher getTextWatcher() {
290        return new PhoneNumberFormattingTextWatcher("US");
291    }
292}
293