package com.badoo.chateau.example.ui.chat; import android.content.Intent; import android.net.Uri; import android.support.annotation.NonNull; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import com.badoo.chateau.data.models.payloads.ImagePayload; import com.badoo.chateau.data.models.payloads.Payload; import com.badoo.chateau.data.models.payloads.TextPayload; import com.badoo.chateau.example.BaseTestCase; import com.badoo.chateau.example.R; import com.badoo.chateau.example.data.model.ExampleMessage; import com.badoo.chateau.example.ui.Injector; import com.badoo.chateau.example.ui.chat.info.ExampleChatInfoPresenter; import com.badoo.chateau.example.ui.chat.input.ExampleChatInputPresenter; import com.badoo.chateau.example.ui.chat.istyping.ExampleIsTypingPresenter; import com.badoo.chateau.example.ui.chat.messages.ExampleMessageListPresenter; import com.badoo.chateau.example.ui.chat.messages.ExampleMessageListView; import com.badoo.chateau.ui.chat.photos.PhotoPresenter; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentMatcher; import org.mockito.Mockito; import java.util.ArrayList; import java.util.List; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.Espresso.registerIdlingResources; import static android.support.test.espresso.Espresso.unregisterIdlingResources; import static android.support.test.espresso.action.ViewActions.click; import static android.support.test.espresso.action.ViewActions.typeText; import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition; import static android.support.test.espresso.contrib.RecyclerViewActions.scrollToPosition; import static android.support.test.espresso.matcher.ViewMatchers.withId; import static com.badoo.chateau.ui.chat.input.ChatInputPresenter.ChatInputView; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @RunWith(AndroidJUnit4.class) public class ChatActivityTest extends BaseTestCase<ChatActivity> { private static final String CHAT_ID = "chatId"; private static final String CHAT_NAME = "chatName"; private static final String MESSAGE = "message"; private ExampleMessageListPresenter mListPresenter; private ExampleChatInputPresenter mInputPresenter; private PhotoPresenter mPhotoPresenter; private ExampleMessageListView mMessageListView; private ExampleIsTypingPresenter mIsTypingPresenter; private ExampleChatInfoPresenter mChatInfoPresenter; @Override protected Class<ChatActivity> getActivityClass() { return ChatActivity.class; } @Override protected Intent getActivityIntent() { return ChatActivity.create(InstrumentationRegistry.getContext(), CHAT_ID, CHAT_NAME); } @Override protected void beforeActivityLaunched() { mListPresenter = mock(ExampleMessageListPresenter.class); mInputPresenter = mock(ExampleChatInputPresenter.class); mPhotoPresenter = mock(PhotoPresenter.class); mIsTypingPresenter = mock(ExampleIsTypingPresenter.class); mChatInfoPresenter = mock(ExampleChatInfoPresenter.class); Injector.register(ChatActivity.class, new ChatActivity.DefaultConfiguration() { @Override protected ExampleMessageListView createMessageListView(@NonNull ChatActivity activity, @NonNull String chatId) { mMessageListView = super.createMessageListView(activity, chatId); return mMessageListView; } @Override protected ExampleMessageListPresenter createMessageListPresenter(@NonNull ExampleMessageListView view, @NonNull ExampleMessageListPresenter.ExampleMessageListFlowListener flowListener, @NonNull String chatId) { return mListPresenter; } @Override protected ExampleChatInputPresenter createTextInputPresenter(@NonNull ChatInputView view, @NonNull String conversationId) { return mInputPresenter; } @Override protected PhotoPresenter createPhotoPresenter(@NonNull PhotoPresenter.PhotoFlowListener flowListener) { return mPhotoPresenter; } @Override protected ExampleChatInfoPresenter createChatInfoPresenter(@NonNull ExampleChatInfoPresenter.ExampleChatInfoView v, @NonNull String conversationId) { return mChatInfoPresenter; } @Override protected ExampleIsTypingPresenter createIsTypingPresenter(@NonNull ExampleIsTypingPresenter.ExampleIsTypingView view, @NonNull String conversationId) { return mIsTypingPresenter; } }); } @Test public void userIsTyping() { // When onView(withId(R.id.chatTextInput_editText)).perform(typeText(MESSAGE)); // Then verify(mIsTypingPresenter).onUserTyping(); } @Test public void sendMessage() { // When onView(withId(R.id.chatTextInput_editText)).perform(typeText(MESSAGE)); onView(withId(R.id.chatTextInput_sendEnabled)).perform(click()); // Then verify(mInputPresenter).onSendMessage(Mockito.argThat(new PayloadMatcher(new TextPayload(MESSAGE)))); } @Test public void startSendingGalleryImage() { // When onView(withId(R.id.action_attachPhoto)).perform(click()); // Then verify(mPhotoPresenter).onPickPhoto(); } @Test public void startTakePhoto() { // When onView(withId(R.id.action_takePhoto)).perform(click()); // Then verify(mPhotoPresenter).onTakePhoto(); } @Test public void clickOnImageMessage() { // Given final List<ExampleMessage> messages = createPhotoMessages(5); runOnUiThread(() -> mMessageListView.showMessages(messages)); // Then onView(withId(R.id.chat_list)).perform(actionOnItemAtPosition(4, click())); // Then Uri uri = Uri.parse(((ImagePayload) messages.get(4).getPayload()).getImageUrl()); verify(mListPresenter).onImageClicked(uri); } @Test public void testLoadMoreWhenScrollToTop() { // Given final List<ExampleMessage> messages = createTextMessages(40); runOnUiThread(() -> mMessageListView.showMessages(messages)); // When onView(withId(R.id.chat_list)).perform(scrollToPosition(0)); // Need to wait for the scroll to complete before we verify if more data was requested final WaitForRecycleViewScrollIdlingResource<ChatActivity> idlingResource = new WaitForRecycleViewScrollIdlingResource<>(R.id.chat_list, 0, mActivityRule); try { registerIdlingResources(idlingResource); // Then verify(mListPresenter).onMoreMessagesRequired(); } finally { unregisterIdlingResources(idlingResource); } } private List<ExampleMessage> createTextMessages(int count) { List<ExampleMessage> messages = new ArrayList<>(); for (int i = 0; i < count; i++) { String id = Integer.toString(i); Payload payload = new TextPayload("msg-" + i); messages.add(new ExampleMessage(id, "", false, "sender", payload, i, false)); } return messages; } private List<ExampleMessage> createPhotoMessages(int count) { List<ExampleMessage> messages = new ArrayList<>(); for (int i = 0; i < count; i++) { String id = Integer.toString(i); Payload payload = new ImagePayload("http://www.badoo.com/broken.png", null, "msg-" + i); messages.add(new ExampleMessage(id, "", false, "sender", payload, i, false)); } return messages; } private static class PayloadMatcher extends ArgumentMatcher<ExampleMessage> { @NonNull private final Payload mExpected; public PayloadMatcher(@NonNull Payload expected) { mExpected = expected; } @Override public boolean matches(Object argument) { ExampleMessage other = (ExampleMessage) argument; return mExpected.equals(other.getPayload()); } } }