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