1/*
2 * Copyright (C) 2010 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
17package com.android.dialer;
18
19import android.content.Context;
20import android.content.res.Resources;
21import android.provider.CallLog.Calls;
22import android.test.AndroidTestCase;
23import android.text.Html;
24import android.text.Spanned;
25import android.view.View;
26import android.widget.TextView;
27
28import com.android.dialer.calllog.CallTypeHelper;
29import com.android.dialer.calllog.TestPhoneNumberUtilsWrapper;
30import com.android.dialer.util.LocaleTestUtils;
31
32import java.util.GregorianCalendar;
33import java.util.Locale;
34
35/**
36 * Unit tests for {@link PhoneCallDetailsHelper}.
37 */
38public class PhoneCallDetailsHelperTest extends AndroidTestCase {
39    /** The number to be used to access the voicemail. */
40    private static final String TEST_VOICEMAIL_NUMBER = "125";
41    /** The date of the call log entry. */
42    private static final long TEST_DATE =
43        new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis();
44    /** A test duration value for phone calls. */
45    private static final long TEST_DURATION = 62300;
46    /** The number of the caller/callee in the log entry. */
47    private static final String TEST_NUMBER = "14125555555";
48    /** The formatted version of {@link #TEST_NUMBER}. */
49    private static final String TEST_FORMATTED_NUMBER = "1-412-255-5555";
50    /** The country ISO name used in the tests. */
51    private static final String TEST_COUNTRY_ISO = "US";
52    /** The geocoded location used in the tests. */
53    private static final String TEST_GEOCODE = "United States";
54
55    /** The object under test. */
56    private PhoneCallDetailsHelper mHelper;
57    /** The views to fill. */
58    private PhoneCallDetailsViews mViews;
59    private TextView mNameView;
60    private LocaleTestUtils mLocaleTestUtils;
61
62    @Override
63    protected void setUp() throws Exception {
64        super.setUp();
65        Context context = getContext();
66        Resources resources = context.getResources();
67        CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
68        final TestPhoneNumberUtilsWrapper phoneUtils = new TestPhoneNumberUtilsWrapper(
69                TEST_VOICEMAIL_NUMBER);
70        mHelper = new PhoneCallDetailsHelper(resources, callTypeHelper, phoneUtils);
71        mHelper.setCurrentTimeForTest(
72                new GregorianCalendar(2011, 5, 4, 13, 0, 0).getTimeInMillis());
73        mViews = PhoneCallDetailsViews.createForTest(context);
74        mNameView = new TextView(context);
75        mLocaleTestUtils = new LocaleTestUtils(getContext());
76        mLocaleTestUtils.setLocale(Locale.US);
77    }
78
79    @Override
80    protected void tearDown() throws Exception {
81        mLocaleTestUtils.restoreLocale();
82        mNameView = null;
83        mViews = null;
84        mHelper = null;
85        super.tearDown();
86    }
87
88    public void testSetPhoneCallDetails_Unknown() {
89        setPhoneCallDetailsWithNumber("", Calls.PRESENTATION_UNKNOWN, "");
90        assertNameEqualsResource(R.string.unknown);
91    }
92
93    public void testSetPhoneCallDetails_Private() {
94        setPhoneCallDetailsWithNumber("", Calls.PRESENTATION_RESTRICTED, "");
95        assertNameEqualsResource(R.string.private_num);
96    }
97
98    public void testSetPhoneCallDetails_Payphone() {
99        setPhoneCallDetailsWithNumber("", Calls.PRESENTATION_PAYPHONE, "");
100        assertNameEqualsResource(R.string.payphone);
101    }
102
103    public void testSetPhoneCallDetails_Voicemail() {
104        setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER,
105                Calls.PRESENTATION_ALLOWED, TEST_VOICEMAIL_NUMBER);
106        assertNameEqualsResource(R.string.voicemail);
107    }
108
109    public void testSetPhoneCallDetails_Normal() {
110        setPhoneCallDetailsWithNumber("14125551212",
111                Calls.PRESENTATION_ALLOWED, "1-412-555-1212");
112        assertEquals("Yesterday", mViews.callTypeAndDate.getText().toString());
113        assertEqualsHtml("<font color='#33b5e5'><b>Yesterday</b></font>",
114                mViews.callTypeAndDate.getText());
115    }
116
117    /** Asserts that a char sequence is actually a Spanned corresponding to the expected HTML. */
118    private void assertEqualsHtml(String expectedHtml, CharSequence actualText) {
119        // In order to contain HTML, the text should actually be a Spanned.
120        assertTrue(actualText instanceof Spanned);
121        Spanned actualSpanned = (Spanned) actualText;
122        // Convert from and to HTML to take care of alternative formatting of HTML.
123        assertEquals(Html.toHtml(Html.fromHtml(expectedHtml)), Html.toHtml(actualSpanned));
124
125    }
126
127    public void testSetPhoneCallDetails_Date() {
128        mHelper.setCurrentTimeForTest(
129                new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis());
130
131        setPhoneCallDetailsWithDate(
132                new GregorianCalendar(2011, 5, 3, 13, 0, 0).getTimeInMillis());
133        assertDateEquals("0 mins ago");
134
135        setPhoneCallDetailsWithDate(
136                new GregorianCalendar(2011, 5, 3, 12, 0, 0).getTimeInMillis());
137        assertDateEquals("1 hour ago");
138
139        setPhoneCallDetailsWithDate(
140                new GregorianCalendar(2011, 5, 2, 13, 0, 0).getTimeInMillis());
141        assertDateEquals("Yesterday");
142
143        setPhoneCallDetailsWithDate(
144                new GregorianCalendar(2011, 5, 1, 13, 0, 0).getTimeInMillis());
145        assertDateEquals("2 days ago");
146    }
147
148    public void testSetPhoneCallDetails_CallTypeIcons() {
149        setPhoneCallDetailsWithCallTypeIcons(Calls.INCOMING_TYPE);
150        assertCallTypeIconsEquals(Calls.INCOMING_TYPE);
151
152        setPhoneCallDetailsWithCallTypeIcons(Calls.OUTGOING_TYPE);
153        assertCallTypeIconsEquals(Calls.OUTGOING_TYPE);
154
155        setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE);
156        assertCallTypeIconsEquals(Calls.MISSED_TYPE);
157
158        setPhoneCallDetailsWithCallTypeIcons(Calls.VOICEMAIL_TYPE);
159        assertCallTypeIconsEquals(Calls.VOICEMAIL_TYPE);
160    }
161
162    public void testSetPhoneCallDetails_MultipleCallTypeIcons() {
163        setPhoneCallDetailsWithCallTypeIcons(Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE);
164        assertCallTypeIconsEquals(Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE);
165
166        setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE, Calls.MISSED_TYPE);
167        assertCallTypeIconsEquals(Calls.MISSED_TYPE, Calls.MISSED_TYPE);
168    }
169
170    public void testSetPhoneCallDetails_MultipleCallTypeIconsLastOneDropped() {
171        setPhoneCallDetailsWithCallTypeIcons(Calls.MISSED_TYPE, Calls.MISSED_TYPE,
172                Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE);
173        assertCallTypeIconsEqualsPlusOverflow("(4)",
174                Calls.MISSED_TYPE, Calls.MISSED_TYPE, Calls.INCOMING_TYPE);
175    }
176
177    public void testSetPhoneCallDetails_Geocode() {
178        setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", "Pennsylvania");
179        assertNameEquals("1-412-555-5555");  // The phone number is shown as the name.
180        assertLabelEquals("Pennsylvania"); // The geocode is shown as the label.
181    }
182
183    public void testSetPhoneCallDetails_NoGeocode() {
184        setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", null);
185        assertNameEquals("1-412-555-5555");  // The phone number is shown as the name.
186        assertLabelEquals("-"); // The empty geocode is shown as the label.
187    }
188
189    public void testSetPhoneCallDetails_EmptyGeocode() {
190        setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", "");
191        assertNameEquals("1-412-555-5555");  // The phone number is shown as the name.
192        assertLabelEquals("-"); // The empty geocode is shown as the label.
193    }
194
195    public void testSetPhoneCallDetails_NoGeocodeForVoicemail() {
196        setPhoneCallDetailsWithNumberAndGeocode(TEST_VOICEMAIL_NUMBER, "", "United States");
197        assertLabelEquals("-"); // The empty geocode is shown as the label.
198    }
199
200    public void testSetPhoneCallDetails_Highlighted() {
201        setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER,
202                Calls.PRESENTATION_ALLOWED, "");
203    }
204
205    public void testSetCallDetailsHeader_NumberOnly() {
206        setCallDetailsHeaderWithNumber(TEST_NUMBER, Calls.PRESENTATION_ALLOWED);
207        assertEquals(View.VISIBLE, mNameView.getVisibility());
208        assertEquals("Add to contacts", mNameView.getText().toString());
209    }
210
211    public void testSetCallDetailsHeader_UnknownNumber() {
212        setCallDetailsHeaderWithNumber("", Calls.PRESENTATION_UNKNOWN);
213        assertEquals(View.VISIBLE, mNameView.getVisibility());
214        assertEquals("Unknown", mNameView.getText().toString());
215    }
216
217    public void testSetCallDetailsHeader_PrivateNumber() {
218        setCallDetailsHeaderWithNumber("", Calls.PRESENTATION_RESTRICTED);
219        assertEquals(View.VISIBLE, mNameView.getVisibility());
220        assertEquals("Private number", mNameView.getText().toString());
221    }
222
223    public void testSetCallDetailsHeader_PayphoneNumber() {
224        setCallDetailsHeaderWithNumber("", Calls.PRESENTATION_PAYPHONE);
225        assertEquals(View.VISIBLE, mNameView.getVisibility());
226        assertEquals("Pay phone", mNameView.getText().toString());
227    }
228
229    public void testSetCallDetailsHeader_VoicemailNumber() {
230        setCallDetailsHeaderWithNumber(TEST_VOICEMAIL_NUMBER, Calls.PRESENTATION_ALLOWED);
231        assertEquals(View.VISIBLE, mNameView.getVisibility());
232        assertEquals("Voicemail", mNameView.getText().toString());
233    }
234
235    public void testSetCallDetailsHeader() {
236        setCallDetailsHeader("John Doe");
237        assertEquals(View.VISIBLE, mNameView.getVisibility());
238        assertEquals("John Doe", mNameView.getText().toString());
239    }
240
241    /** Asserts that the name text field contains the value of the given string resource. */
242    private void assertNameEqualsResource(int resId) {
243        assertNameEquals(getContext().getString(resId));
244    }
245
246    /** Asserts that the name text field contains the given string value. */
247    private void assertNameEquals(String text) {
248        assertEquals(text, mViews.nameView.getText().toString());
249    }
250
251    /** Asserts that the label text field contains the given string value. */
252    private void assertLabelEquals(String text) {
253        assertEquals(text, mViews.labelView.getText().toString());
254    }
255
256    /** Asserts that the date text field contains the given string value. */
257    private void assertDateEquals(String text) {
258        assertEquals(text, mViews.callTypeAndDate.getText().toString());
259    }
260
261    /** Asserts that the call type contains the images with the given drawables. */
262    private void assertCallTypeIconsEquals(int... ids) {
263        assertEquals(ids.length, mViews.callTypeIcons.getCount());
264        for (int index = 0; index < ids.length; ++index) {
265            int id = ids[index];
266            assertEquals(id, mViews.callTypeIcons.getCallType(index));
267        }
268        assertEquals(View.VISIBLE, mViews.callTypeIcons.getVisibility());
269        assertEquals("Yesterday", mViews.callTypeAndDate.getText().toString());
270    }
271
272    /**
273     * Asserts that the call type contains the images with the given drawables and shows the given
274     * text next to the icons.
275     */
276    private void assertCallTypeIconsEqualsPlusOverflow(String overflowText, int... ids) {
277        assertEquals(ids.length, mViews.callTypeIcons.getCount());
278        for (int index = 0; index < ids.length; ++index) {
279            int id = ids[index];
280            assertEquals(id, mViews.callTypeIcons.getCallType(index));
281        }
282        assertEquals(View.VISIBLE, mViews.callTypeIcons.getVisibility());
283        assertEquals(overflowText + " Yesterday", mViews.callTypeAndDate.getText().toString());
284    }
285
286    /** Sets the phone call details with default values and the given number. */
287    private void setPhoneCallDetailsWithNumber(String number, int presentation,
288            String formattedNumber) {
289        mHelper.setPhoneCallDetails(mViews,
290                new PhoneCallDetails(number, presentation, formattedNumber,
291                        TEST_COUNTRY_ISO, TEST_GEOCODE,
292                        new int[]{ Calls.VOICEMAIL_TYPE }, TEST_DATE, TEST_DURATION),
293                true);
294    }
295
296    /** Sets the phone call details with default values and the given number. */
297    private void setPhoneCallDetailsWithNumberAndGeocode(String number, String formattedNumber,
298            String geocodedLocation) {
299        mHelper.setPhoneCallDetails(mViews,
300                new PhoneCallDetails(number, Calls.PRESENTATION_ALLOWED,
301                        formattedNumber, TEST_COUNTRY_ISO, geocodedLocation,
302                        new int[]{ Calls.VOICEMAIL_TYPE }, TEST_DATE, TEST_DURATION),
303                true);
304    }
305
306    /** Sets the phone call details with default values and the given date. */
307    private void setPhoneCallDetailsWithDate(long date) {
308        mHelper.setPhoneCallDetails(mViews,
309                new PhoneCallDetails(TEST_NUMBER, Calls.PRESENTATION_ALLOWED,
310                        TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO, TEST_GEOCODE,
311                        new int[]{ Calls.INCOMING_TYPE }, date, TEST_DURATION),
312                false);
313    }
314
315    /** Sets the phone call details with default values and the given call types using icons. */
316    private void setPhoneCallDetailsWithCallTypeIcons(int... callTypes) {
317        mHelper.setPhoneCallDetails(mViews,
318                new PhoneCallDetails(TEST_NUMBER, Calls.PRESENTATION_ALLOWED,
319                        TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO, TEST_GEOCODE,
320                        callTypes, TEST_DATE, TEST_DURATION),
321                false);
322    }
323
324    private void setCallDetailsHeaderWithNumber(String number, int presentation) {
325        mHelper.setCallDetailsHeader(mNameView,
326                new PhoneCallDetails(number, presentation,
327                        TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO, TEST_GEOCODE,
328                        new int[]{ Calls.INCOMING_TYPE }, TEST_DATE, TEST_DURATION));
329    }
330
331    private void setCallDetailsHeader(String name) {
332        mHelper.setCallDetailsHeader(mNameView,
333                new PhoneCallDetails(TEST_NUMBER, Calls.PRESENTATION_ALLOWED,
334                        TEST_FORMATTED_NUMBER, TEST_COUNTRY_ISO, TEST_GEOCODE,
335                        new int[]{ Calls.INCOMING_TYPE }, TEST_DATE, TEST_DURATION,
336                        name, 0, "", null, null));
337    }
338}
339