Initial checkin of AOSP Messaging app.
b/23110861 Change-Id: I9aa980d7569247d6b2ca78f5dcb4502e1eaadb8a
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.messaging.ui.conversation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.android.messaging.FakeFactory;
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.DataModel;
|
||||
import com.android.messaging.datamodel.binding.Binding;
|
||||
import com.android.messaging.datamodel.binding.BindingBase;
|
||||
import com.android.messaging.datamodel.data.ConversationData;
|
||||
import com.android.messaging.datamodel.data.DraftMessageData;
|
||||
import com.android.messaging.datamodel.data.DraftMessageData.CheckDraftForSendTask;
|
||||
import com.android.messaging.datamodel.data.DraftMessageData.CheckDraftTaskCallback;
|
||||
import com.android.messaging.datamodel.data.MessageData;
|
||||
import com.android.messaging.datamodel.data.MessagePartData;
|
||||
import com.android.messaging.ui.ViewTest;
|
||||
import com.android.messaging.ui.conversation.ComposeMessageView.IComposeMessageViewHost;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.FakeMediaUtil;
|
||||
import com.android.messaging.util.ImeUtil;
|
||||
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
@MediumTest
|
||||
public class ComposeMessageViewTest extends ViewTest<ComposeMessageView> {
|
||||
private Context mContext;
|
||||
|
||||
@Mock protected DataModel mockDataModel;
|
||||
@Mock protected DraftMessageData mockDraftMessageData;
|
||||
@Mock protected BugleGservices mockBugleGservices;
|
||||
@Mock protected ImeUtil mockImeUtil;
|
||||
@Mock protected IComposeMessageViewHost mockIComposeMessageViewHost;
|
||||
@Mock protected MediaPlayer mockMediaPlayer;
|
||||
@Mock protected ConversationInputManager mockInputManager;
|
||||
@Mock protected ConversationData mockConversationData;
|
||||
|
||||
Binding<ConversationData> mConversationBinding;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mContext = getInstrumentation().getTargetContext();
|
||||
FakeFactory.register(mContext)
|
||||
.withDataModel(mockDataModel)
|
||||
.withBugleGservices(mockBugleGservices)
|
||||
.withMediaUtil(new FakeMediaUtil(mockMediaPlayer));
|
||||
|
||||
Mockito.doReturn(true).when(mockConversationData).isBound(Mockito.anyString());
|
||||
mConversationBinding = BindingBase.createBinding(this);
|
||||
mConversationBinding.bind(mockConversationData);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ComposeMessageView getView() {
|
||||
final ComposeMessageView view = super.getView();
|
||||
view.setInputManager(mockInputManager);
|
||||
view.setConversationDataModel(BindingBase.createBindingReference(mConversationBinding));
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutIdForView() {
|
||||
return R.layout.compose_message_view;
|
||||
}
|
||||
|
||||
public void testSend() {
|
||||
Mockito.when(mockDraftMessageData.getReadOnlyAttachments())
|
||||
.thenReturn(Collections.unmodifiableList(new ArrayList<MessagePartData>()));
|
||||
Mockito.when(mockDraftMessageData.getIsDefaultSmsApp()).thenReturn(true);
|
||||
Mockito.when(mockIComposeMessageViewHost.isReadyForAction()).thenReturn(true);
|
||||
final ComposeMessageView view = getView();
|
||||
|
||||
final MessageData message = MessageData.createDraftSmsMessage("fake_id", "just_a_self_id",
|
||||
"Sample Message");
|
||||
|
||||
Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
|
||||
.thenReturn(true);
|
||||
Mockito.when(mockDraftMessageData.getMessageText()).thenReturn(message.getMessageText());
|
||||
Mockito.when(mockDraftMessageData.prepareMessageForSending(
|
||||
Matchers.<BindingBase<DraftMessageData>>any()))
|
||||
.thenReturn(message);
|
||||
Mockito.when(mockDraftMessageData.hasPendingAttachments()).thenReturn(false);
|
||||
Mockito.doAnswer(new Answer() {
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
// Synchronously pass the draft check and callback.
|
||||
((CheckDraftTaskCallback)invocation.getArguments()[2]).onDraftChecked(
|
||||
mockDraftMessageData, CheckDraftForSendTask.RESULT_PASSED);
|
||||
return null;
|
||||
}
|
||||
}).when(mockDraftMessageData).checkDraftForAction(Mockito.anyBoolean(), Mockito.anyInt(),
|
||||
Mockito.<CheckDraftTaskCallback>any(),
|
||||
Mockito.<Binding<DraftMessageData>>any());
|
||||
|
||||
view.bind(mockDraftMessageData, mockIComposeMessageViewHost);
|
||||
|
||||
final EditText composeEditText = (EditText) view.findViewById(R.id.compose_message_text);
|
||||
final View sendButton = view.findViewById(R.id.send_message_button);
|
||||
|
||||
view.requestDraftMessage(false);
|
||||
|
||||
Mockito.verify(mockDraftMessageData).loadFromStorage(Matchers.any(BindingBase.class),
|
||||
Matchers.any(MessageData.class), Mockito.eq(false));
|
||||
|
||||
view.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
|
||||
|
||||
assertEquals(message.getMessageText(), composeEditText.getText().toString());
|
||||
|
||||
sendButton.performClick();
|
||||
Mockito.verify(mockIComposeMessageViewHost).sendMessage(
|
||||
Mockito.argThat(new ArgumentMatcher<MessageData>() {
|
||||
@Override
|
||||
public boolean matches(final Object o) {
|
||||
assertEquals(message.getMessageText(), ((MessageData) o).getMessageText());
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void testNotDefaultSms() {
|
||||
Mockito.when(mockDraftMessageData.getReadOnlyAttachments())
|
||||
.thenReturn(Collections.unmodifiableList(new ArrayList<MessagePartData>()));
|
||||
Mockito.when(mockDraftMessageData.getIsDefaultSmsApp()).thenReturn(false);
|
||||
Mockito.when(mockIComposeMessageViewHost.isReadyForAction()).thenReturn(false);
|
||||
final ComposeMessageView view = getView();
|
||||
|
||||
final MessageData message = MessageData.createDraftSmsMessage("fake_id", "just_a_self_id",
|
||||
"Sample Message");
|
||||
|
||||
Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
|
||||
.thenReturn(true);
|
||||
Mockito.when(mockDraftMessageData.getMessageText()).thenReturn(message.getMessageText());
|
||||
Mockito.when(mockDraftMessageData.prepareMessageForSending(
|
||||
Matchers.<BindingBase<DraftMessageData>>any()))
|
||||
.thenReturn(message);
|
||||
Mockito.when(mockDraftMessageData.hasPendingAttachments()).thenReturn(false);
|
||||
|
||||
view.bind(mockDraftMessageData, mockIComposeMessageViewHost);
|
||||
|
||||
final EditText composeEditText = (EditText) view.findViewById(R.id.compose_message_text);
|
||||
final View sendButton = view.findViewById(R.id.send_message_button);
|
||||
|
||||
view.requestDraftMessage(false);
|
||||
|
||||
Mockito.verify(mockDraftMessageData).loadFromStorage(Matchers.any(BindingBase.class),
|
||||
Matchers.any(MessageData.class), Mockito.eq(false));
|
||||
|
||||
view.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
|
||||
|
||||
assertEquals(message.getMessageText(), composeEditText.getText().toString());
|
||||
|
||||
sendButton.performClick();
|
||||
Mockito.verify(mockIComposeMessageViewHost).warnOfMissingActionConditions(
|
||||
Matchers.any(Boolean.class), Matchers.any(Runnable.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.messaging.ui.conversation;
|
||||
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.messaging.BugleTestCase;
|
||||
import com.android.messaging.ui.contact.ContactPickerFragment;
|
||||
import com.android.messaging.ui.conversation.ConversationActivityUiState;
|
||||
import com.android.messaging.ui.conversation.ConversationActivityUiState.ConversationActivityUiStateHost;
|
||||
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
@SmallTest
|
||||
public class ConversationActivityUiStateTest extends BugleTestCase {
|
||||
@Mock protected ConversationActivityUiStateHost mockListener;
|
||||
|
||||
/**
|
||||
* Test the Ui state where we start off with the contact picker to pick the first contact.
|
||||
*/
|
||||
public void testPickInitialContact() {
|
||||
final ConversationActivityUiState uiState = new ConversationActivityUiState(null);
|
||||
uiState.setHost(mockListener);
|
||||
assertTrue(uiState.shouldShowContactPickerFragment());
|
||||
assertFalse(uiState.shouldShowConversationFragment());
|
||||
assertEquals(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT,
|
||||
uiState.getDesiredContactPickingMode());
|
||||
uiState.onGetOrCreateConversation("conversation1");
|
||||
Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
|
||||
Mockito.eq(ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_INITIAL_CONTACT),
|
||||
Mockito.eq(
|
||||
ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW),
|
||||
Mockito.anyBoolean());
|
||||
assertTrue(uiState.shouldShowContactPickerFragment());
|
||||
assertTrue(uiState.shouldShowConversationFragment());
|
||||
assertTrue(TextUtils.equals("conversation1", uiState.getConversationId()));
|
||||
assertEquals(ContactPickerFragment.MODE_CHIPS_ONLY,
|
||||
uiState.getDesiredContactPickingMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the Ui state where we have both the chips view and the conversation view and we
|
||||
* start message compose.
|
||||
*/
|
||||
public void testHybridUiStateStartCompose() {
|
||||
final ConversationActivityUiState uiState = new ConversationActivityUiState("conv1");
|
||||
uiState.testSetUiState(
|
||||
ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW);
|
||||
uiState.setHost(mockListener);
|
||||
|
||||
// Start message compose.
|
||||
uiState.onStartMessageCompose();
|
||||
Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
|
||||
Mockito.eq(
|
||||
ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW),
|
||||
Mockito.eq(ConversationActivityUiState.STATE_CONVERSATION_ONLY),
|
||||
Mockito.anyBoolean());
|
||||
assertFalse(uiState.shouldShowContactPickerFragment());
|
||||
assertTrue(uiState.shouldShowConversationFragment());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the Ui state where we have both the chips view and the conversation view and we
|
||||
* try to add a participant.
|
||||
*/
|
||||
public void testHybridUiStateAddParticipant() {
|
||||
final ConversationActivityUiState uiState = new ConversationActivityUiState("conv1");
|
||||
uiState.testSetUiState(
|
||||
ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW);
|
||||
uiState.setHost(mockListener);
|
||||
|
||||
uiState.onAddMoreParticipants();
|
||||
Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
|
||||
Mockito.eq(
|
||||
ConversationActivityUiState.STATE_HYBRID_WITH_CONVERSATION_AND_CHIPS_VIEW),
|
||||
Mockito.eq(
|
||||
ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS),
|
||||
Mockito.anyBoolean());
|
||||
assertTrue(uiState.shouldShowContactPickerFragment());
|
||||
assertFalse(uiState.shouldShowConversationFragment());
|
||||
assertEquals(ContactPickerFragment.MODE_PICK_MORE_CONTACTS,
|
||||
uiState.getDesiredContactPickingMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the Ui state where we are trying to add more participants and commit.
|
||||
*/
|
||||
public void testCommitAddParticipant() {
|
||||
final ConversationActivityUiState uiState = new ConversationActivityUiState(null);
|
||||
uiState.testSetUiState(
|
||||
ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS);
|
||||
uiState.setHost(mockListener);
|
||||
|
||||
uiState.onGetOrCreateConversation("conversation1");
|
||||
|
||||
// After adding more contacts, the terminal state is always conversation only (i.e. we
|
||||
// don't go back to hybrid mode).
|
||||
Mockito.verify(mockListener, Mockito.times(1)).onConversationContactPickerUiStateChanged(
|
||||
Mockito.eq(ConversationActivityUiState.STATE_CONTACT_PICKER_ONLY_ADD_MORE_CONTACTS),
|
||||
Mockito.eq(ConversationActivityUiState.STATE_CONVERSATION_ONLY),
|
||||
Mockito.anyBoolean());
|
||||
assertFalse(uiState.shouldShowContactPickerFragment());
|
||||
assertTrue(uiState.shouldShowConversationFragment());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.messaging.ui.conversation;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.database.Cursor;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
|
||||
import com.android.messaging.FakeFactory;
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.DataModel;
|
||||
import com.android.messaging.datamodel.MemoryCacheManager;
|
||||
import com.android.messaging.datamodel.data.ConversationData;
|
||||
import com.android.messaging.datamodel.data.ConversationData.ConversationDataListener;
|
||||
import com.android.messaging.datamodel.data.DraftMessageData;
|
||||
import com.android.messaging.datamodel.data.TestDataFactory;
|
||||
import com.android.messaging.datamodel.media.MediaResourceManager;
|
||||
import com.android.messaging.ui.FragmentTestCase;
|
||||
import com.android.messaging.ui.PlainTextEditText;
|
||||
import com.android.messaging.ui.TestActivity.FragmentEventListener;
|
||||
import com.android.messaging.ui.conversation.ConversationFragment.ConversationFragmentHost;
|
||||
import com.android.messaging.ui.conversationlist.ConversationListFragment;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.ImeUtil;
|
||||
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ConversationListFragment}.
|
||||
*/
|
||||
@LargeTest
|
||||
public class ConversationFragmentTest extends FragmentTestCase<ConversationFragment> {
|
||||
|
||||
@Mock protected DataModel mockDataModel;
|
||||
@Mock protected ConversationData mockConversationData;
|
||||
@Mock protected DraftMessageData mockDraftMessageData;
|
||||
@Mock protected MediaResourceManager mockMediaResourceManager;
|
||||
@Mock protected BugleGservices mockBugleGservices;
|
||||
@Mock protected ConversationFragmentHost mockHost;
|
||||
@Mock protected MemoryCacheManager mockMemoryCacheManager;
|
||||
|
||||
private ImeUtil mSpiedImeUtil;
|
||||
|
||||
private static final String CONVERSATION_ID = "cid";
|
||||
|
||||
|
||||
public ConversationFragmentTest() {
|
||||
super(ConversationFragment.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ImeUtil.clearInstance();
|
||||
mSpiedImeUtil = Mockito.spy(new ImeUtil());
|
||||
FakeFactory.register(this.getInstrumentation().getTargetContext())
|
||||
.withDataModel(mockDataModel)
|
||||
.withBugleGservices(mockBugleGservices)
|
||||
.withMemoryCacheManager(mockMemoryCacheManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper that will do the 'binding' of ConversationFragmentTest with ConversationData and
|
||||
* leave fragment in 'ready' state.
|
||||
* @param cursor
|
||||
*/
|
||||
private void loadWith(final Cursor cursor) {
|
||||
Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
|
||||
.thenReturn(true);
|
||||
Mockito.when(mockConversationData.isBound(Matchers.anyString()))
|
||||
.thenReturn(true);
|
||||
Mockito.doReturn(mockDraftMessageData)
|
||||
.when(mockDataModel)
|
||||
.createDraftMessageData(Mockito.anyString());
|
||||
Mockito.when(mockDataModel.createConversationData(
|
||||
Matchers.any(Activity.class),
|
||||
Matchers.any(ConversationDataListener.class),
|
||||
Matchers.anyString()))
|
||||
.thenReturn(mockConversationData);
|
||||
|
||||
// Create fragment synchronously to avoid need for volatile, synchronization etc.
|
||||
final ConversationFragment fragment = getFragment();
|
||||
// Binding to model happens when attaching fragment to activity, so hook into test
|
||||
// activity to do so.
|
||||
getActivity().setFragmentEventListener(new FragmentEventListener() {
|
||||
@Override
|
||||
public void onAttachFragment(final Fragment attachedFragment) {
|
||||
if (fragment == attachedFragment) {
|
||||
fragment.setConversationInfo(getActivity(), CONVERSATION_ID, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fragment.setHost(mockHost);
|
||||
getActivity().setFragment(fragment);
|
||||
Mockito.verify(mockDataModel).createConversationData(
|
||||
getActivity(), fragment, CONVERSATION_ID);
|
||||
Mockito.verify(mockConversationData).init(fragment.getLoaderManager(),
|
||||
fragment.mBinding);
|
||||
}
|
||||
});
|
||||
// Wait for initial layout pass to work around crash in recycler view
|
||||
getInstrumentation().waitForIdleSync();
|
||||
// Now load the cursor
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fragment.onConversationMessagesCursorUpdated(mockConversationData, cursor, null,
|
||||
false);
|
||||
}
|
||||
});
|
||||
getInstrumentation().waitForIdleSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that list view gets correctly populated given a cursor.
|
||||
*/
|
||||
public void testLoadListView() {
|
||||
final Cursor cursor = TestDataFactory.getConversationMessageCursor();
|
||||
loadWith(cursor);
|
||||
final RecyclerView listView =
|
||||
(RecyclerView) getFragment().getView().findViewById(android.R.id.list);
|
||||
assertEquals("bad cursor", cursor.getCount(), listView.getAdapter().getItemCount());
|
||||
assertEquals("bad cursor count", cursor.getCount(), listView.getChildCount());
|
||||
}
|
||||
|
||||
public void testClickComposeMessageView() {
|
||||
final Cursor cursor = TestDataFactory.getConversationMessageCursor();
|
||||
loadWith(cursor);
|
||||
|
||||
final PlainTextEditText composeEditText = (PlainTextEditText) getFragment().getView()
|
||||
.findViewById(R.id.compose_message_text);
|
||||
setFocus(composeEditText, false);
|
||||
Mockito.verify(mockHost, Mockito.never()).onStartComposeMessage();
|
||||
setFocus(composeEditText, true);
|
||||
Mockito.verify(mockHost).onStartComposeMessage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.messaging.ui.conversation;
|
||||
|
||||
import android.app.FragmentManager;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.os.Bundle;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.android.messaging.BugleTestCase;
|
||||
import com.android.messaging.FakeFactory;
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.binding.Binding;
|
||||
import com.android.messaging.datamodel.binding.BindingBase;
|
||||
import com.android.messaging.datamodel.data.ConversationData;
|
||||
import com.android.messaging.datamodel.data.DraftMessageData;
|
||||
import com.android.messaging.datamodel.data.SubscriptionListData;
|
||||
import com.android.messaging.ui.conversation.ConversationInputManager.ConversationInputHost;
|
||||
import com.android.messaging.ui.conversation.ConversationInputManager.ConversationInputSink;
|
||||
import com.android.messaging.ui.mediapicker.MediaPicker;
|
||||
import com.android.messaging.util.BugleGservices;
|
||||
import com.android.messaging.util.ImeUtil;
|
||||
import com.android.messaging.util.ImeUtil.ImeStateHost;
|
||||
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
|
||||
@SmallTest
|
||||
public class ConversationInputManagerTest extends BugleTestCase {
|
||||
@Spy protected ImeUtil spyImeUtil;
|
||||
@Mock protected BugleGservices mockBugleGservices;
|
||||
@Mock protected FragmentManager mockFragmentManager;
|
||||
@Mock protected ConversationInputHost mockConversationInputHost;
|
||||
@Mock protected ConversationInputSink mockConversationInputSink;
|
||||
@Mock protected ImeStateHost mockImeStateHost;
|
||||
@Mock protected ConversationData mockConversationData;
|
||||
@Mock protected DraftMessageData mockDraftMessageData;
|
||||
@Mock protected MediaPicker mockMediaPicker;
|
||||
@Mock protected SubscriptionListData mockSubscriptionListData;
|
||||
@Mock protected FragmentTransaction mockFragmentTransaction;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
FakeFactory.register(getTestContext())
|
||||
.withBugleGservices(mockBugleGservices);
|
||||
spyImeUtil = Mockito.spy(new ImeUtil());
|
||||
ImeUtil.set(spyImeUtil);
|
||||
}
|
||||
|
||||
private ConversationInputManager initNewInputManager(final Bundle savedState) {
|
||||
// Set up the mocks.
|
||||
Mockito.when(mockConversationInputHost.getSimSelectorView())
|
||||
.thenReturn(new SimSelectorView(getTestContext(), null));
|
||||
Mockito.when(mockConversationInputHost.createMediaPicker()).thenReturn(mockMediaPicker);
|
||||
Mockito.when(mockConversationInputSink.getComposeEditText())
|
||||
.thenReturn(new EditText(getTestContext()));
|
||||
Mockito.doReturn(mockFragmentTransaction).when(mockFragmentTransaction).replace(
|
||||
Mockito.eq(R.id.mediapicker_container), Mockito.any(MediaPicker.class),
|
||||
Mockito.anyString());
|
||||
Mockito.when(mockFragmentManager.findFragmentByTag(MediaPicker.FRAGMENT_TAG))
|
||||
.thenReturn(null);
|
||||
Mockito.when(mockFragmentManager.beginTransaction()).thenReturn(mockFragmentTransaction);
|
||||
Mockito.when(mockSubscriptionListData.hasData()).thenReturn(true);
|
||||
Mockito.when(mockConversationData.getSubscriptionListData())
|
||||
.thenReturn(mockSubscriptionListData);
|
||||
Mockito.doReturn(true).when(mockConversationData).isBound(Mockito.anyString());
|
||||
Mockito.doReturn(true).when(mockDraftMessageData).isBound(Mockito.anyString());
|
||||
|
||||
final Binding<ConversationData> dataBinding = BindingBase.createBinding(this);
|
||||
dataBinding.bind(mockConversationData);
|
||||
final Binding<DraftMessageData> draftBinding = BindingBase.createBinding(this);
|
||||
draftBinding.bind(mockDraftMessageData);
|
||||
final ConversationInputManager inputManager = new ConversationInputManager(getTestContext(),
|
||||
mockConversationInputHost, mockConversationInputSink, mockImeStateHost,
|
||||
mockFragmentManager, dataBinding, draftBinding, savedState);
|
||||
return inputManager;
|
||||
}
|
||||
|
||||
public void testShowHideInputs() {
|
||||
final ConversationInputManager inputManager = initNewInputManager(new Bundle());
|
||||
Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
|
||||
inputManager.showHideMediaPicker(true /* show */, true /* animate */);
|
||||
Mockito.verify(mockFragmentTransaction).replace(
|
||||
Mockito.eq(R.id.mediapicker_container), Mockito.any(MediaPicker.class),
|
||||
Mockito.anyString());
|
||||
Mockito.verify(mockMediaPicker).open(Mockito.anyInt(), Mockito.eq(true /* animate */));
|
||||
|
||||
assertEquals(true, inputManager.isMediaPickerVisible());
|
||||
assertEquals(false, inputManager.isSimSelectorVisible());
|
||||
assertEquals(false, inputManager.isImeKeyboardVisible());
|
||||
|
||||
Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
|
||||
inputManager.showHideMediaPicker(false /* show */, true /* animate */);
|
||||
Mockito.verify(mockMediaPicker).dismiss(Mockito.eq(true /* animate */));
|
||||
|
||||
assertEquals(false, inputManager.isMediaPickerVisible());
|
||||
assertEquals(false, inputManager.isSimSelectorVisible());
|
||||
assertEquals(false, inputManager.isImeKeyboardVisible());
|
||||
}
|
||||
|
||||
public void testShowTwoInputsSequentially() {
|
||||
// First show the media picker, then show the IME keyboard.
|
||||
final ConversationInputManager inputManager = initNewInputManager(new Bundle());
|
||||
Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
|
||||
inputManager.showHideMediaPicker(true /* show */, true /* animate */);
|
||||
|
||||
assertEquals(true, inputManager.isMediaPickerVisible());
|
||||
assertEquals(false, inputManager.isSimSelectorVisible());
|
||||
assertEquals(false, inputManager.isImeKeyboardVisible());
|
||||
|
||||
Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
|
||||
inputManager.showHideImeKeyboard(true /* show */, true /* animate */);
|
||||
|
||||
assertEquals(false, inputManager.isMediaPickerVisible());
|
||||
assertEquals(false, inputManager.isSimSelectorVisible());
|
||||
assertEquals(true, inputManager.isImeKeyboardVisible());
|
||||
}
|
||||
|
||||
public void testOnKeyboardShow() {
|
||||
final ConversationInputManager inputManager = initNewInputManager(new Bundle());
|
||||
Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
|
||||
inputManager.showHideMediaPicker(true /* show */, true /* animate */);
|
||||
|
||||
assertEquals(true, inputManager.isMediaPickerVisible());
|
||||
assertEquals(false, inputManager.isSimSelectorVisible());
|
||||
assertEquals(false, inputManager.isImeKeyboardVisible());
|
||||
|
||||
Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
|
||||
inputManager.testNotifyImeStateChanged(true /* imeOpen */);
|
||||
|
||||
assertEquals(false, inputManager.isMediaPickerVisible());
|
||||
assertEquals(false, inputManager.isSimSelectorVisible());
|
||||
assertEquals(true, inputManager.isImeKeyboardVisible());
|
||||
}
|
||||
|
||||
public void testRestoreState() {
|
||||
final ConversationInputManager inputManager = initNewInputManager(new Bundle());
|
||||
Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
|
||||
inputManager.showHideMediaPicker(true /* show */, true /* animate */);
|
||||
|
||||
assertEquals(true, inputManager.isMediaPickerVisible());
|
||||
assertEquals(false, inputManager.isSimSelectorVisible());
|
||||
assertEquals(false, inputManager.isImeKeyboardVisible());
|
||||
|
||||
Bundle savedInstanceState = new Bundle();
|
||||
inputManager.onSaveInputState(savedInstanceState);
|
||||
|
||||
// Now try to restore the state
|
||||
final ConversationInputManager restoredInputManager =
|
||||
initNewInputManager(savedInstanceState);
|
||||
|
||||
// Make sure the state is preserved.
|
||||
assertEquals(true, restoredInputManager.isMediaPickerVisible());
|
||||
assertEquals(false, restoredInputManager.isSimSelectorVisible());
|
||||
assertEquals(false, restoredInputManager.isImeKeyboardVisible());
|
||||
}
|
||||
|
||||
public void testBackPress() {
|
||||
final ConversationInputManager inputManager = initNewInputManager(new Bundle());
|
||||
Mockito.when(mockMediaPicker.isOpen()).thenReturn(true);
|
||||
inputManager.showHideMediaPicker(true /* show */, true /* animate */);
|
||||
|
||||
assertEquals(true, inputManager.isMediaPickerVisible());
|
||||
assertEquals(false, inputManager.isSimSelectorVisible());
|
||||
assertEquals(false, inputManager.isImeKeyboardVisible());
|
||||
|
||||
Mockito.when(mockMediaPicker.isOpen()).thenReturn(false);
|
||||
assertEquals(true, inputManager.onBackPressed());
|
||||
|
||||
assertEquals(false, inputManager.isMediaPickerVisible());
|
||||
assertEquals(false, inputManager.isSimSelectorVisible());
|
||||
assertEquals(false, inputManager.isImeKeyboardVisible());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.messaging.ui.conversation;
|
||||
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.Suppress;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.messaging.FakeFactory;
|
||||
import com.android.messaging.R;
|
||||
import com.android.messaging.datamodel.FakeCursor;
|
||||
import com.android.messaging.datamodel.data.TestDataFactory;
|
||||
import com.android.messaging.ui.ViewTest;
|
||||
import com.android.messaging.ui.conversation.ConversationMessageView;
|
||||
import com.android.messaging.ui.conversation.ConversationMessageView.ConversationMessageViewHost;
|
||||
import com.android.messaging.util.Dates;
|
||||
|
||||
import org.mockito.Mock;
|
||||
|
||||
@MediumTest
|
||||
public class ConversationMessageViewTest extends ViewTest<ConversationMessageView> {
|
||||
@Mock ConversationMessageViewHost mockHost;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
FakeFactory.register(getInstrumentation().getTargetContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConversationMessageView getView() {
|
||||
final ConversationMessageView view = super.getView();
|
||||
view.setHost(mockHost);
|
||||
return view;
|
||||
}
|
||||
|
||||
protected void verifyContent(final ConversationMessageView view, final String messageText,
|
||||
final boolean showTimestamp, final String timestampText) {
|
||||
|
||||
final TextView messageTextView = (TextView) view.findViewById(R.id.message_text);
|
||||
final TextView statusTextView = (TextView) view.findViewById(R.id.message_status);
|
||||
|
||||
assertNotNull(messageTextView);
|
||||
assertEquals(messageText, messageTextView.getText());
|
||||
|
||||
if (showTimestamp) {
|
||||
assertEquals(View.VISIBLE, statusTextView.getVisibility());
|
||||
assertEquals(timestampText, statusTextView.getText());
|
||||
} else {
|
||||
assertEquals(View.GONE, statusTextView.getVisibility());
|
||||
}
|
||||
}
|
||||
|
||||
public void testBind() {
|
||||
final ConversationMessageView view = getView();
|
||||
|
||||
final FakeCursor cursor = TestDataFactory.getConversationMessageCursor();
|
||||
cursor.moveToFirst();
|
||||
|
||||
view.bind(cursor);
|
||||
verifyContent(view, TestDataFactory.getMessageText(cursor, 0), true, Dates
|
||||
.getMessageTimeString((Long) cursor.getAt("received_timestamp", 0)).toString());
|
||||
}
|
||||
|
||||
public void testBindTwice() {
|
||||
final ConversationMessageView view = getView();
|
||||
|
||||
final FakeCursor cursor = TestDataFactory.getConversationMessageCursor();
|
||||
cursor.moveToFirst();
|
||||
view.bind(cursor);
|
||||
|
||||
cursor.moveToNext();
|
||||
view.bind(cursor);
|
||||
verifyContent(view, TestDataFactory.getMessageText(cursor, 1), true, Dates
|
||||
.getMessageTimeString((Long) cursor.getAt("received_timestamp", 1)).toString());
|
||||
}
|
||||
|
||||
public void testBindLast() {
|
||||
final ConversationMessageView view = getView();
|
||||
|
||||
final FakeCursor cursor = TestDataFactory.getConversationMessageCursor();
|
||||
final int lastPos = cursor.getCount() - 1;
|
||||
cursor.moveToPosition(lastPos);
|
||||
|
||||
view.bind(cursor);
|
||||
verifyContent(view, TestDataFactory.getMessageText(cursor, lastPos), true, Dates
|
||||
.getMessageTimeString((Long) cursor.getAt("received_timestamp", lastPos))
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutIdForView() {
|
||||
return R.layout.conversation_message_view;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user