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 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 ConversationFragmentTest()66 public ConversationFragmentTest() { 67 super(ConversationFragment.class); 68 } 69 70 @Override setUp()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 */ loadWith(final Cursor cursor)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.doReturn(mockDraftMessageData) 95 .when(mockDataModel) 96 .createDraftMessageData(null); 97 Mockito.when(mockDataModel.createConversationData( 98 Matchers.any(Activity.class), 99 Matchers.any(ConversationDataListener.class), 100 Matchers.anyString())) 101 .thenReturn(mockConversationData); 102 103 // Create fragment synchronously to avoid need for volatile, synchronization etc. 104 final ConversationFragment fragment = getFragment(); 105 // Binding to model happens when attaching fragment to activity, so hook into test 106 // activity to do so. 107 getActivity().setFragmentEventListener(new FragmentEventListener() { 108 @Override 109 public void onAttachFragment(final Fragment attachedFragment) { 110 if (fragment == attachedFragment) { 111 fragment.setConversationInfo(getActivity(), CONVERSATION_ID, null); 112 } 113 } 114 }); 115 116 getActivity().runOnUiThread(new Runnable() { 117 @Override 118 public void run() { 119 fragment.setHost(mockHost); 120 getActivity().setFragment(fragment); 121 Mockito.verify(mockDataModel).createConversationData( 122 getActivity(), fragment, CONVERSATION_ID); 123 Mockito.verify(mockConversationData).init(fragment.getLoaderManager(), 124 fragment.mBinding); 125 } 126 }); 127 // Wait for initial layout pass to work around crash in recycler view 128 getInstrumentation().waitForIdleSync(); 129 // Now load the cursor 130 getActivity().runOnUiThread(new Runnable() { 131 @Override 132 public void run() { 133 fragment.onConversationMessagesCursorUpdated(mockConversationData, cursor, null, 134 false); 135 } 136 }); 137 getInstrumentation().waitForIdleSync(); 138 } 139 140 /** 141 * Verifies that list view gets correctly populated given a cursor. 142 */ testLoadListView()143 public void testLoadListView() { 144 final Cursor cursor = TestDataFactory.getConversationMessageCursor(); 145 loadWith(cursor); 146 final RecyclerView listView = 147 (RecyclerView) getFragment().getView().findViewById(android.R.id.list); 148 assertEquals("bad cursor", cursor.getCount(), listView.getAdapter().getItemCount()); 149 assertEquals("bad cursor count", cursor.getCount(), listView.getChildCount()); 150 } 151 testClickComposeMessageView()152 public void testClickComposeMessageView() { 153 final Cursor cursor = TestDataFactory.getConversationMessageCursor(); 154 loadWith(cursor); 155 156 final PlainTextEditText composeEditText = (PlainTextEditText) getFragment().getView() 157 .findViewById(R.id.compose_message_text); 158 setFocus(composeEditText, false); 159 Mockito.verify(mockHost, Mockito.never()).onStartComposeMessage(); 160 setFocus(composeEditText, true); 161 Mockito.verify(mockHost).onStartComposeMessage(); 162 } 163 } 164