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