Home | History | Annotate | Download | only in conversation
      1 /*
      2  * Copyright (C) 2015 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.messaging.ui.conversation;
     18 
     19 import android.app.Activity;
     20 import android.app.Fragment;
     21 import android.database.Cursor;
     22 import android.support.v7.widget.RecyclerView;
     23 import android.test.suitebuilder.annotation.LargeTest;
     24 
     25 import com.android.messaging.FakeFactory;
     26 import com.android.messaging.R;
     27 import com.android.messaging.datamodel.DataModel;
     28 import com.android.messaging.datamodel.MemoryCacheManager;
     29 import com.android.messaging.datamodel.data.ConversationData;
     30 import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
     31 import com.android.messaging.datamodel.data.DraftMessageData;
     32 import com.android.messaging.datamodel.data.TestDataFactory;
     33 import com.android.messaging.datamodel.media.MediaResourceManager;
     34 import com.android.messaging.ui.FragmentTestCase;
     35 import com.android.messaging.ui.PlainTextEditText;
     36 import com.android.messaging.ui.TestActivity.FragmentEventListener;
     37 import com.android.messaging.ui.conversation.ConversationFragment.ConversationFragmentHost;
     38 import com.android.messaging.ui.conversationlist.ConversationListFragment;
     39 import com.android.messaging.util.BugleGservices;
     40 import com.android.messaging.util.ImeUtil;
     41 
     42 import org.mockito.Matchers;
     43 import org.mockito.Mock;
     44 import org.mockito.Mockito;
     45 
     46 
     47 /**
     48  * Unit tests for {@link ConversationListFragment}.
     49  */
     50 @LargeTest
     51 public class ConversationFragmentTest extends FragmentTestCase<ConversationFragment> {
     52 
     53     @Mock protected DataModel mockDataModel;
     54     @Mock protected ConversationData mockConversationData;
     55     @Mock protected DraftMessageData mockDraftMessageData;
     56     @Mock protected MediaResourceManager mockMediaResourceManager;
     57     @Mock protected BugleGservices mockBugleGservices;
     58     @Mock protected ConversationFragmentHost mockHost;
     59     @Mock protected MemoryCacheManager mockMemoryCacheManager;
     60 
     61     private ImeUtil mSpiedImeUtil;
     62 
     63     private static final String CONVERSATION_ID = "cid";
     64 
     65 
     66     public ConversationFragmentTest() {
     67         super(ConversationFragment.class);
     68     }
     69 
     70     @Override
     71     protected void setUp() throws Exception {
     72       super.setUp();
     73       ImeUtil.clearInstance();
     74       mSpiedImeUtil = Mockito.spy(new ImeUtil());
     75       FakeFactory.register(this.getInstrumentation().getTargetContext())
     76           .withDataModel(mockDataModel)
     77           .withBugleGservices(mockBugleGservices)
     78           .withMemoryCacheManager(mockMemoryCacheManager);
     79     }
     80 
     81     /**
     82      * Helper that will do the 'binding' of ConversationFragmentTest with ConversationData and
     83      * leave fragment in 'ready' state.
     84      * @param cursor
     85      */
     86     private void loadWith(final Cursor cursor) {
     87         Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
     88             .thenReturn(true);
     89         Mockito.when(mockConversationData.isBound(Matchers.anyString()))
     90             .thenReturn(true);
     91         Mockito.doReturn(mockDraftMessageData)
     92             .when(mockDataModel)
     93             .createDraftMessageData(Mockito.anyString());
     94         Mockito.when(mockDataModel.createConversationData(
     95                 Matchers.any(Activity.class),
     96                 Matchers.any(ConversationDataListener.class),
     97                 Matchers.anyString()))
     98             .thenReturn(mockConversationData);
     99 
    100         // Create fragment synchronously to avoid need for volatile, synchronization etc.
    101         final ConversationFragment fragment = getFragment();
    102         // Binding to model happens when attaching fragment to activity, so hook into test
    103         // activity to do so.
    104         getActivity().setFragmentEventListener(new FragmentEventListener() {
    105             @Override
    106             public void onAttachFragment(final Fragment attachedFragment) {
    107                 if (fragment == attachedFragment) {
    108                     fragment.setConversationInfo(getActivity(), CONVERSATION_ID, null);
    109                 }
    110             }
    111         });
    112 
    113         getActivity().runOnUiThread(new Runnable() {
    114             @Override
    115             public void run() {
    116                 fragment.setHost(mockHost);
    117                 getActivity().setFragment(fragment);
    118                 Mockito.verify(mockDataModel).createConversationData(
    119                         getActivity(), fragment, CONVERSATION_ID);
    120                 Mockito.verify(mockConversationData).init(fragment.getLoaderManager(),
    121                         fragment.mBinding);
    122             }
    123         });
    124         // Wait for initial layout pass to work around crash in recycler view
    125         getInstrumentation().waitForIdleSync();
    126         // Now load the cursor
    127         getActivity().runOnUiThread(new Runnable() {
    128             @Override
    129             public void run() {
    130                 fragment.onConversationMessagesCursorUpdated(mockConversationData, cursor, null,
    131                         false);
    132             }
    133         });
    134         getInstrumentation().waitForIdleSync();
    135     }
    136 
    137     /**
    138      * Verifies that list view gets correctly populated given a cursor.
    139      */
    140     public void testLoadListView() {
    141         final Cursor cursor = TestDataFactory.getConversationMessageCursor();
    142         loadWith(cursor);
    143         final RecyclerView listView =
    144                 (RecyclerView) getFragment().getView().findViewById(android.R.id.list);
    145         assertEquals("bad cursor", cursor.getCount(), listView.getAdapter().getItemCount());
    146         assertEquals("bad cursor count", cursor.getCount(), listView.getChildCount());
    147     }
    148 
    149     public void testClickComposeMessageView() {
    150         final Cursor cursor = TestDataFactory.getConversationMessageCursor();
    151         loadWith(cursor);
    152 
    153         final PlainTextEditText composeEditText = (PlainTextEditText) getFragment().getView()
    154                 .findViewById(R.id.compose_message_text);
    155         setFocus(composeEditText, false);
    156         Mockito.verify(mockHost, Mockito.never()).onStartComposeMessage();
    157         setFocus(composeEditText, true);
    158         Mockito.verify(mockHost).onStartComposeMessage();
    159     }
    160 }
    161