Initial checkin of AOSP Messaging app.

b/23110861

Change-Id: I9aa980d7569247d6b2ca78f5dcb4502e1eaadb8a
This commit is contained in:
Mike Dodd
2015-08-11 11:16:59 -07:00
parent 8b3e2b9c1b
commit 461a34b466
1645 changed files with 186271 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
/*
* 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;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
/**
* Purpose of this class is providing a workaround for https://b/14561718
*/
public class ActivityInstrumentationTestCaseIntent extends Intent {
public ActivityInstrumentationTestCaseIntent(Context packageContext, Class<?> cls) {
super(packageContext, cls);
}
@Override
public Intent setComponent(ComponentName component) {
// Ignore the ComponentName set, as the one ActivityUnitTest does is wrong (and actually
// unnecessary).
return this;
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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;
import android.app.Activity;
import com.android.messaging.BugleTestCase;
import com.android.messaging.TestUtil;
/**
* Helper class that extends ActivityInstrumentationTestCase2 to provide some extra common
* initialization (eg. Mockito boilerplate).
*/
public class BugleActivityInstrumentationTestCase<T extends Activity>
extends android.test.ActivityInstrumentationTestCase2<T> {
static {
// Set flag during loading of test cases to prevent application initialization starting
BugleTestCase.setTestsRunning();
}
public BugleActivityInstrumentationTestCase(final Class<T> activityClass) {
super(activityClass);
}
@Override
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
TestUtil.testSetup(getInstrumentation().getTargetContext(), this);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
TestUtil.testTeardown(this);
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.DataModel;
import org.mockito.Mock;
import org.mockito.Mockito;
public abstract class BugleActivityTest extends BugleActivityUnitTestCase<BugleActionBarActivity> {
@Mock protected DataModel mDataModel;
public BugleActivityTest() {
super(BugleActionBarActivity.class);
}
@SuppressWarnings("unchecked")
@Override
protected void setUp() throws Exception {
super.setUp();
// Create activity
final ActivityInstrumentationTestCaseIntent intent =
new ActivityInstrumentationTestCaseIntent(getInstrumentation().getTargetContext(),
TestActivity.class);
startActivity(intent, null, null);
FakeFactory.register(getInstrumentation().getTargetContext())
.withDataModel(mDataModel);
}
public void testOnResumeDataModelCallback() {
getInstrumentation().callActivityOnStart(getActivity());
getInstrumentation().callActivityOnResume(getActivity());
Mockito.verify(mDataModel).onActivityResume();
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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;
import android.app.Activity;
import android.view.ContextThemeWrapper;
import com.android.messaging.BugleTestCase;
import com.android.messaging.R;
import com.android.messaging.TestUtil;
/**
* Base class for activity unit test cases, provides boilerplate setup/teardown.
*/
public abstract class BugleActivityUnitTestCase<T extends Activity> extends
android.test.ActivityUnitTestCase<T> {
static {
// Set flag during loading of test cases to prevent application initialization starting
BugleTestCase.setTestsRunning();
}
public BugleActivityUnitTestCase(final Class<T> activityClass) {
super(activityClass);
}
@SuppressWarnings("unchecked")
@Override
protected void setUp() throws Exception {
super.setUp();
TestUtil.testSetup(getInstrumentation().getTargetContext(), this);
setActivityContext(new ContextThemeWrapper(getInstrumentation().getTargetContext(),
R.style.Theme_AppCompat_Light_DarkActionBar));
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
TestUtil.testTeardown(this);
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SimpleCursorAdapter;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
public class CustomHeaderViewPagerTest extends ViewTest<CustomHeaderViewPager> {
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(getInstrumentation().getTargetContext());
}
public void testBindFirstLevel() {
final CustomHeaderViewPager view = new CustomHeaderViewPager(getActivity(), null);
final SimpleCursorAdapter adapter =
new SimpleCursorAdapter(getActivity(), 0, null, null, null, 0);
final CustomHeaderPagerViewHolder[] viewHolders = {
new FakeListViewHolder(getActivity(), adapter),
new FakeListViewHolder(getActivity(), adapter)
};
view.setViewHolders(viewHolders);
final ViewPager pager = (ViewPager) view.findViewById(R.id.pager);
final ViewGroup tabStrip = (ViewGroup) view.findViewById(R.id.tab_strip);
final ViewPagerTabStrip realTab = (ViewPagerTabStrip) tabStrip.getChildAt(0);
assertEquals(2, realTab.getChildCount());
View headerTitleButton = realTab.getChildAt(1);
// Click on the first page. Now the view pager should switch to that page accordingly.
clickButton(headerTitleButton);
assertEquals(1, pager.getCurrentItem());
}
@Override
protected int getLayoutIdForView() {
// All set up should be done by creating a CustomHeaderViewPager which handles inflating
// the layout
return 0;
}
}

View File

@@ -0,0 +1,60 @@
/*
* 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;
import android.content.Context;
import android.widget.CursorAdapter;
import com.android.messaging.R;
/**
* A fake {@link CustomHeaderPagerListViewHolder} for CustomHeaderViewPager tests only.
*/
public class FakeListViewHolder extends CustomHeaderPagerListViewHolder {
public FakeListViewHolder(final Context context, final CursorAdapter adapter) {
super(context, adapter);
}
@Override
protected int getLayoutResId() {
return 0;
}
@Override
protected int getPageTitleResId() {
return android.R.string.untitled;
}
@Override
protected int getEmptyViewResId() {
return R.id.empty_view;
}
@Override
protected int getListViewResId() {
return android.R.id.list;
}
@Override
protected int getEmptyViewTitleResId() {
return R.string.contact_list_empty_text;
}
@Override
protected int getEmptyViewImageResId() {
return R.drawable.ic_oobe_freq_list;
}
}

View File

@@ -0,0 +1,120 @@
/*
* 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;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.res.Configuration;
import android.view.View;
/**
* Helper class that extends Bugle.ui.ActivityInstrumentationTestCase to provide common behavior
* across fragment tests.
*/
public abstract class FragmentTestCase<T extends Fragment>
extends BugleActivityInstrumentationTestCase<TestActivity> {
protected T mFragment;
protected Class<T> mFragmentClass;
public FragmentTestCase(final Class<T> fragmentClass) {
super(TestActivity.class);
mFragmentClass = fragmentClass;
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
protected T getFragment() {
// Fragment creation deferred (typically until test time) so that factory/appcontext is
// ready.
if (mFragment == null) {
try {
mFragment = mFragmentClass.newInstance();
} catch (final InstantiationException e) {
throw new IllegalStateException("Failed to instantiate fragment");
} catch (final IllegalAccessException e) {
throw new IllegalStateException("Failed to instantiate fragment");
}
}
return mFragment;
}
protected void attachFragment() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
final FragmentManager fragmentManager = getActivity().getFragmentManager();
fragmentManager.beginTransaction().add(mFragment, null /* tag */).commit();
}
});
getInstrumentation().waitForIdleSync();
}
@Override
protected void tearDown() throws Exception {
// In landscape mode, sleep for a second first.
// The reason is: our UI tests don't wait for the UI thread to finish settling down
// before exiting (because they can't know when the UI thread is done). In portrait mode,
// things generally work fine here -- the UI thread is done by the time the test is done.
// In landscape mode, though, since the launcher is in portrait mode, there is a lot of
// extra work that happens in our UI when the app launches into landscape mode, and the
// UI is often not done by the time the test finishes running. So then our teardown
// nulls out the Factory, and then the UI keeps running and derefs the null factory,
// and things blow up.
// So ... as a cheap hack, sleep for one second before finishing the teardown of UI
// tests, but only do it in landscape mode (so that developers running it in portrait
// mode can still run the tests faster).
if (this.getInstrumentation().getTargetContext().getResources().
getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
super.tearDown();
}
protected void clickButton(final View view) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
view.performClick();
}
});
getInstrumentation().waitForIdleSync();
}
protected void setFocus(final View view, final boolean focused) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (focused) {
view.requestFocus();
} else {
view.clearFocus();
}
}
});
getInstrumentation().waitForIdleSync();
}
}

View File

@@ -0,0 +1,122 @@
/*
* 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;
import android.content.Context;
import android.net.Uri;
import android.test.suitebuilder.annotation.MediumTest;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.data.MessagePartData;
import java.util.Arrays;
import java.util.Collections;
@MediumTest
public class MultiAttachmentLayoutTest extends ViewTest<MultiAttachmentLayout> {
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
FakeFactory.register(context);
}
@Override
protected MultiAttachmentLayout getView() {
if (mView == null) {
// View creation deferred (typically until test time) so that factory/appcontext is
// ready.
mView = new MultiAttachmentLayout(getActivity(), null);
mView.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
}
return mView;
}
protected void verifyContent(
final MultiAttachmentLayout view,
final int imageCount,
final int plusCount) {
final int count = view.getChildCount();
int actualImageCount = 0;
final boolean needPlusText = plusCount > 0;
boolean hasPlusText = false;
for (int i = 0; i < count; i++) {
final View child = view.getChildAt(i);
if (child instanceof AsyncImageView) {
actualImageCount++;
} else if (child instanceof TextView) {
assertTrue(plusCount > 0);
assertTrue(((TextView) child).getText().toString().contains("" + plusCount));
hasPlusText = true;
} else {
// Nothing other than image and overflow text view should appear in this layout.
fail("unexpected view in layout. view = " + child);
}
}
assertEquals(imageCount, actualImageCount);
assertEquals(needPlusText, hasPlusText);
}
public void testBindTwoAttachments() {
final MultiAttachmentLayout view = getView();
final MessagePartData testAttachment1 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri1"), 100, 100);
final MessagePartData testAttachment2 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri2"), 100, 100);
view.bindAttachments(createAttachmentList(testAttachment1, testAttachment2),
null /* transitionRect */, 2);
verifyContent(view, 2, 0);
}
public void testBindFiveAttachments() {
final MultiAttachmentLayout view = getView();
final MessagePartData testAttachment1 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri1"), 100, 100);
final MessagePartData testAttachment2 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri2"), 100, 100);
final MessagePartData testAttachment3 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri3"), 100, 100);
final MessagePartData testAttachment4 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri4"), 100, 100);
final MessagePartData testAttachment5 = MessagePartData.createMediaMessagePart(
"image/jpeg", Uri.parse("content://uri5"), 100, 100);
view.bindAttachments(createAttachmentList(testAttachment1, testAttachment2, testAttachment3,
testAttachment4, testAttachment5), null /* transitionRect */, 5);
verifyContent(view, 4, 1);
}
public void testBindTwice() {
// Put the above two tests together so we can simulate binding twice.
testBindTwoAttachments();
testBindFiveAttachments();
}
private Iterable<MessagePartData> createAttachmentList(final MessagePartData... attachments) {
return Collections.unmodifiableList(Arrays.asList(attachments));
}
@Override
protected int getLayoutIdForView() {
return 0; // We construct the view with getView().
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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;
import android.view.View;
/**
* Base class for view tests. Derived class just has to provide a layout id. Tests can then just
* call getView() to get a created view and test its behavior.
*/
public abstract class ViewTest<T extends View> extends BugleActivityUnitTestCase<TestActivity> {
public ViewTest() {
super(TestActivity.class);
}
protected T mView;
@SuppressWarnings("unchecked")
@Override
protected void setUp() throws Exception {
super.setUp();
// Create activity
final ActivityInstrumentationTestCaseIntent intent =
new ActivityInstrumentationTestCaseIntent(getInstrumentation().getTargetContext(),
TestActivity.class);
startActivity(intent, null, null);
}
@SuppressWarnings("unchecked")
protected T getView() {
if (mView == null) {
// View creation deferred (typically until test time) so that factory/appcontext is
// ready.
mView = (T) getActivity().getLayoutInflater().inflate(getLayoutIdForView(), null);
}
return mView;
}
protected void clickButton(final View view) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
view.performClick();
}
});
getInstrumentation().waitForIdleSync();
}
protected abstract int getLayoutIdForView();
}

View File

@@ -0,0 +1,172 @@
/*
* 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.attachmentchooser;
import android.app.Fragment;
import android.test.suitebuilder.annotation.LargeTest;
import android.widget.CheckBox;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.DataModel;
import com.android.messaging.datamodel.data.DraftMessageData;
import com.android.messaging.datamodel.data.MessageData;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.FragmentTestCase;
import com.android.messaging.ui.TestActivity;
import com.android.messaging.ui.TestActivity.FragmentEventListener;
import com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment;
import com.android.messaging.ui.attachmentchooser.AttachmentGridItemView;
import com.android.messaging.ui.attachmentchooser.AttachmentGridView;
import com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment.AttachmentChooserFragmentHost;
import com.android.messaging.ui.conversationlist.ConversationListFragment;
import org.mockito.ArgumentMatcher;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Unit tests for {@link ConversationListFragment}.
*/
@LargeTest
public class AttachmentChooserFragmentTest extends FragmentTestCase<AttachmentChooserFragment> {
@Mock protected DataModel mockDataModel;
@Mock protected DraftMessageData mockDraftMessageData;
@Mock protected AttachmentChooserFragmentHost mockHost;
private static final String CONVERSATION_ID = "cid";
/** A custom argument matcher that checks whether the set argument passed in is a set
* with identical attachment data as the given set.
*/
private class IsSetOfGivenAttachments extends ArgumentMatcher<Set<MessagePartData>> {
private final Set<MessagePartData> mGivenParts;
public IsSetOfGivenAttachments(final Set<MessagePartData> givenParts) {
mGivenParts = givenParts;
}
@Override
public boolean matches(final Object set) {
@SuppressWarnings("unchecked")
final Set<MessagePartData> actualSet = (Set<MessagePartData>) set;
if (actualSet.size() != mGivenParts.size()) {
return false;
}
return mGivenParts.containsAll(actualSet) && actualSet.containsAll(mGivenParts);
}
}
public AttachmentChooserFragmentTest() {
super(AttachmentChooserFragment.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(this.getInstrumentation().getTargetContext())
.withDataModel(mockDataModel);
}
private void loadWith(final List<MessagePartData> attachments) {
Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
.thenReturn(true);
Mockito.doReturn(mockDraftMessageData)
.when(mockDataModel)
.createDraftMessageData(Mockito.anyString());
Mockito.doReturn(attachments)
.when(mockDraftMessageData)
.getReadOnlyAttachments();
Mockito.when(mockDataModel.createDraftMessageData(
Matchers.anyString()))
.thenReturn(mockDraftMessageData);
// Create fragment synchronously to avoid need for volatile, synchronization etc.
final AttachmentChooserFragment 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.setConversationId(CONVERSATION_ID);
}
}
});
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
fragment.setHost(mockHost);
getActivity().setFragment(fragment);
Mockito.verify(mockDataModel).createDraftMessageData(
Mockito.matches(CONVERSATION_ID));
Mockito.verify(mockDraftMessageData).loadFromStorage(
Matchers.eq(fragment.mBinding), Matchers.eq((MessageData) null),
Matchers.eq(false));
}
});
// Now load the cursor
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
fragment.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
}
});
getInstrumentation().waitForIdleSync();
}
public void testUnselect() {
final List<MessagePartData> attachments = TestDataFactory.getTestDraftAttachments();
loadWith(attachments);
final AttachmentGridView attachmentGridView = (AttachmentGridView)
getFragment().getView().findViewById(R.id.grid);
assertEquals("bad view count", attachments.size(),
attachmentGridView.getAdapter().getCount());
final AttachmentGridItemView itemView = (AttachmentGridItemView)
attachmentGridView.getChildAt(0);
assertEquals(attachmentGridView, itemView.testGetHostInterface());
final CheckBox checkBox = (CheckBox) itemView.findViewById(R.id.checkbox);
assertEquals(true, checkBox.isChecked());
assertEquals(true, attachmentGridView.isItemSelected(itemView.mAttachmentData));
clickButton(checkBox);
assertEquals(false, checkBox.isChecked());
assertEquals(false, attachmentGridView.isItemSelected(itemView.mAttachmentData));
final AttachmentGridItemView itemView2 = (AttachmentGridItemView)
attachmentGridView.getChildAt(1);
final CheckBox checkBox2 = (CheckBox) itemView2.findViewById(R.id.checkbox);
clickButton(checkBox2);
getFragment().confirmSelection();
final MessagePartData[] attachmentsToRemove = new MessagePartData[] {
itemView.mAttachmentData, itemView2.mAttachmentData };
Mockito.verify(mockDraftMessageData).removeExistingAttachments(Matchers.argThat(
new IsSetOfGivenAttachments(new HashSet<>(Arrays.asList(attachmentsToRemove)))));
Mockito.verify(mockDraftMessageData).saveToStorage(Matchers.eq(getFragment().mBinding));
Mockito.verify(mockHost).onConfirmSelection();
}
}

View File

@@ -0,0 +1,127 @@
/*
* 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.contact;
import android.content.Context;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
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.FakeDataModel;
import com.android.messaging.datamodel.data.ContactListItemData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.ContactIconView;
import com.android.messaging.ui.ViewTest;
import org.mockito.Mock;
import org.mockito.Mockito;
public class ContactListItemViewTest extends ViewTest<ContactListItemView> {
@Mock ContactListItemView.HostInterface mockHost;
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
FakeFactory.register(context)
.withDataModel(new FakeDataModel(context));
}
protected void verifyAddedContactForData(final ContactListItemData data,
final ContactListItemView view) {
Mockito.verify(mockHost).onContactListItemClicked(data, view);
}
protected void verifyContent(
final ContactListItemView view,
final String contactName,
final String contactDetail,
final String avatarUrl,
final boolean showAvatar) {
final TextView contactNameView = (TextView) view.findViewById(R.id.contact_name);
final TextView contactDetailView = (TextView) view.findViewById(R.id.contact_details);
final ContactIconView avatarView = (ContactIconView) view.findViewById(R.id.contact_icon);
assertNotNull(contactNameView);
assertEquals(contactName, contactNameView.getText());
assertNotNull(contactDetail);
assertEquals(contactDetail, contactDetailView.getText());
assertNotNull(avatarView);
if (showAvatar) {
assertTrue(avatarView.mImageRequestBinding.isBound());
assertEquals(View.VISIBLE, avatarView.getVisibility());
} else {
assertFalse(avatarView.mImageRequestBinding.isBound());
assertEquals(View.INVISIBLE, avatarView.getVisibility());
}
}
public void testBindFirstLevel() {
final ContactListItemView view = getView();
final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
final int row = TestDataFactory.CONTACT_LIST_CURSOR_FIRST_LEVEL_CONTACT_INDEX;
cursor.moveToPosition(row);
view.bind(cursor, mockHost, false, null);
verifyContent(view, (String) cursor.getAt(Contacts.DISPLAY_NAME, row),
(String) cursor.getAt(Phone.NUMBER, row),
(String) cursor.getAt(Contacts.PHOTO_THUMBNAIL_URI, row), true);
}
public void testBindSecondLevel() {
final ContactListItemView view = getView();
final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
final int row = TestDataFactory.CONTACT_LIST_CURSOR_SECOND_LEVEL_CONTACT_INDEX;
cursor.moveToPosition(row);
view.bind(cursor, mockHost, false, null);
verifyContent(view, (String) cursor.getAt(Contacts.DISPLAY_NAME, row),
(String) cursor.getAt(Phone.NUMBER, row),
(String) cursor.getAt(Contacts.PHOTO_THUMBNAIL_URI, row), false);
}
public void testClickAddedContact() {
final ContactListItemView view = getView();
final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
cursor.moveToFirst();
view.bind(cursor, mockHost, false, null);
view.performClick();
verifyAddedContactForData(view.mData, view);
}
public void testBindTwice() {
final ContactListItemView view = getView();
final FakeCursor cursor = TestDataFactory.getAllContactListCursor();
cursor.moveToFirst();
view.bind(cursor, mockHost, false, null);
cursor.moveToNext();
view.bind(cursor, mockHost, false, null);
verifyContent(view, (String) cursor.getAt(Contacts.DISPLAY_NAME, 1),
(String) cursor.getAt(Phone.NUMBER, 1),
(String) cursor.getAt(Contacts.PHOTO_THUMBNAIL_URI, 1), true);
}
@Override
protected int getLayoutIdForView() {
return R.layout.contact_list_item_view;
}
}

View File

@@ -0,0 +1,221 @@
/*
* 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.contact;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.view.ViewPager;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.View;
import android.widget.ListView;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.action.ActionTestHelpers;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService.StubActionServiceCallLog;
import com.android.messaging.datamodel.action.GetOrCreateConversationAction;
import com.android.messaging.datamodel.data.ContactPickerData;
import com.android.messaging.datamodel.data.ParticipantData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.CustomHeaderViewPagerAdapter;
import com.android.messaging.ui.FragmentTestCase;
import com.android.messaging.ui.UIIntents;
import com.android.messaging.ui.contact.ContactPickerFragment.ContactPickerFragmentHost;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.List;
/**
* Unit tests for {@link ContactPickerFragment}.
*/
@LargeTest
public class ContactPickerFragmentTest
extends FragmentTestCase<ContactPickerFragment> {
@Mock protected ContactPickerData mMockContactPickerData;
@Mock protected UIIntents mMockUIIntents;
@Mock protected ContactPickerFragmentHost mockHost;
protected FakeDataModel mFakeDataModel;
private ActionTestHelpers.StubActionService mService;
public ContactPickerFragmentTest() {
super(ContactPickerFragment.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
mService = new StubActionService();
mFakeDataModel = new FakeDataModel(context)
.withContactPickerData(mMockContactPickerData)
.withActionService(mService);
FakeFactory.register(context)
.withDataModel(mFakeDataModel)
.withUIIntents(mMockUIIntents);
}
/**
* Helper method to initialize the ContactPickerFragment and its data.
*/
private ContactPickerFragmentTest initFragment(final int initialMode) {
Mockito.when(mMockContactPickerData.isBound(Matchers.anyString()))
.thenReturn(true);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
final ContactPickerFragment fragment = getFragment();
fragment.setHost(mockHost);
fragment.setContactPickingMode(initialMode, false);
getActivity().setFragment(fragment);
Mockito.verify(mMockContactPickerData).init(fragment.getLoaderManager(),
fragment.mBinding);
}
});
getInstrumentation().waitForIdleSync();
return this;
}
/**
* Bind the datamodel with all contacts cursor to populate the all contacts list in the
* fragment.
*/
private ContactPickerFragmentTest loadWithAllContactsCursor(final Cursor cursor) {
Mockito.when(mMockContactPickerData.isBound(Matchers.anyString()))
.thenReturn(true);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
getFragment().onAllContactsCursorUpdated(cursor);
}
});
getInstrumentation().waitForIdleSync();
return this;
}
/**
* Bind the datamodel with frequent contacts cursor to populate the contacts list in the
* fragment.
*/
private ContactPickerFragmentTest loadWithFrequentContactsCursor(final Cursor cursor) {
Mockito.when(mMockContactPickerData.isBound(Matchers.anyString()))
.thenReturn(true);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
getFragment().onFrequentContactsCursorUpdated(cursor);
}
});
getInstrumentation().waitForIdleSync();
return this;
}
/**
* Test the initial state of the fragment before loading data.
*/
public void testInitialState() {
initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT);
// Make sure that the frequent contacts view is shown by default.
final ViewPager pager = (ViewPager) getFragment().getView().findViewById(R.id.pager);
final View currentPagedView = pager.getChildAt(pager.getCurrentItem());
final View frequentContactsView = ((CustomHeaderViewPagerAdapter) pager.getAdapter())
.getViewHolder(0).getView(null);
assertEquals(frequentContactsView, currentPagedView);
}
/**
* Verifies that list view gets correctly populated given a cursor.
*/
public void testLoadAllContactsList() {
final Cursor cursor = TestDataFactory.getAllContactListCursor();
initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT)
.loadWithAllContactsCursor(cursor);
final ListView listView = (ListView) getFragment().getView()
.findViewById(R.id.all_contacts_list);
assertEquals(cursor.getCount(), listView.getCount());
}
/**
* Verifies that list view gets correctly populated given a cursor.
*/
public void testLoadFrequentContactsList() {
final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT)
.loadWithFrequentContactsCursor(cursor);
final ListView listView = (ListView) getFragment().getView()
.findViewById(R.id.frequent_contacts_list);
assertEquals(cursor.getCount(), listView.getCount());
}
public void testPickInitialContact() {
final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
initFragment(ContactPickerFragment.MODE_PICK_INITIAL_CONTACT)
.loadWithFrequentContactsCursor(cursor);
final ListView listView = (ListView) getFragment().getView()
.findViewById(R.id.frequent_contacts_list);
// Click on the first contact to add it.
final ContactListItemView cliv = (ContactListItemView) listView.getChildAt(0);
clickButton(cliv);
final ContactRecipientAutoCompleteView chipsView = (ContactRecipientAutoCompleteView)
getFragment().getView()
.findViewById(R.id.recipient_text_view);
// Verify the contact is added to the chips view.
final List<ParticipantData> participants =
chipsView.getRecipientParticipantDataForConversationCreation();
assertEquals(1, participants.size());
assertEquals(cliv.mData.getDestination(), participants.get(0).getSendDestination());
assertTrue(mService.getCalls().get(0).action instanceof GetOrCreateConversationAction);
}
public void testLeaveChipsMode() {
final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
initFragment(ContactPickerFragment.MODE_CHIPS_ONLY)
.loadWithFrequentContactsCursor(cursor);
// Click on the add more participants button
// TODO: Figure out a way to click on the add more participants button now that
// it's part of the menu.
// final ImageButton AddMoreParticipantsButton = (ImageButton) getFragment().getView()
// .findViewById(R.id.add_more_participants_button);
// clickButton(AddMoreParticipantsButton);
// Mockito.verify(mockHost).onInitiateAddMoreParticipants();
}
public void testPickMoreContacts() {
final Cursor cursor = TestDataFactory.getFrequentContactListCursor();
initFragment(ContactPickerFragment.MODE_PICK_MORE_CONTACTS)
.loadWithFrequentContactsCursor(cursor);
final ListView listView = (ListView) getFragment().getView()
.findViewById(R.id.frequent_contacts_list);
// Click on the first contact to add it.
final ContactListItemView cliv = (ContactListItemView) listView.getChildAt(0);
clickButton(cliv);
// Verify that we don't attempt to create a conversation right away.
assertEquals(0, mService.getCalls().size());
}
}

View File

@@ -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));
}
}

View File

@@ -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());
}
}

View File

@@ -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();
}
}

View File

@@ -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());
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,130 @@
/*
* 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.conversationlist;
import android.content.Context;
import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.data.ConversationListData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.FragmentTestCase;
import com.android.messaging.ui.UIIntents;
import com.android.messaging.ui.conversationlist.ConversationListFragment;
import com.android.messaging.ui.conversationlist.ConversationListFragment.ConversationListFragmentHost;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
/**
* Unit tests for {@link ConversationListFragment}.
*/
@LargeTest
public class ConversationListFragmentTest
extends FragmentTestCase<ConversationListFragment> {
@Mock protected ConversationListData mMockConversationListData;
@Mock protected ConversationListFragmentHost mMockConversationHostListHost;
@Mock protected UIIntents mMockUIIntents;
protected FakeDataModel mFakeDataModel;
public ConversationListFragmentTest() {
super(ConversationListFragment.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
mFakeDataModel = new FakeDataModel(context)
.withConversationListData(mMockConversationListData);
FakeFactory.register(context)
.withDataModel(mFakeDataModel)
.withUIIntents(mMockUIIntents);
}
/**
* Helper that will do the 'binding' of ConversationListFragmentTest with ConversationListData
* and leave fragment in 'ready' state.
* @param cursor
*/
private void loadWith(final Cursor cursor) {
Mockito.when(mMockConversationListData.isBound(Matchers.anyString()))
.thenReturn(true);
final ConversationListFragment fragment = getFragment();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
fragment.setHost(mMockConversationHostListHost);
getActivity().setFragment(fragment);
Mockito.verify(mMockConversationListData).init(fragment.getLoaderManager(),
fragment.mListBinding);
fragment.onConversationListCursorUpdated(mMockConversationListData, cursor);
}
});
getInstrumentation().waitForIdleSync();
}
/**
* Verifies that list view gets correctly populated given a cursor.
*/
public void testLoadListView() {
final Cursor cursor = TestDataFactory.getConversationListCursor();
loadWith(cursor);
final RecyclerView listView =
(RecyclerView) getFragment().getView().findViewById(android.R.id.list);
//assertEquals(cursor.getCount(), listView.getCount());
assertEquals(cursor.getCount(), listView.getChildCount());
}
/**
* Verifies that 'empty list' promo is rendered with an empty cursor.
*/
public void testEmptyView() {
loadWith(TestDataFactory.getEmptyConversationListCursor());
final RecyclerView listView =
(RecyclerView) getFragment().getView().findViewById(android.R.id.list);
final View emptyMessageView =
getFragment().getView().findViewById(R.id.no_conversations_view);
assertEquals(View.VISIBLE, emptyMessageView.getVisibility());
assertEquals(0, listView.getChildCount());
}
/**
* Verifies that the button to start a new conversation works.
*/
public void testStartNewConversation() {
final Cursor cursor = TestDataFactory.getConversationListCursor();
loadWith(cursor);
final ImageView startNewConversationButton = (ImageView)
getFragment().getView().findViewById(R.id.start_new_conversation_button);
clickButton(startNewConversationButton);
Mockito.verify(mMockConversationHostListHost).onCreateConversationClick();
}
}

View File

@@ -0,0 +1,181 @@
/*
* 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.conversationlist;
import android.content.Context;
import android.test.suitebuilder.annotation.MediumTest;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import com.android.messaging.Factory;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeCursor;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.data.ConversationListItemData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.AsyncImageView;
import com.android.messaging.ui.UIIntentsImpl;
import com.android.messaging.ui.ViewTest;
import com.android.messaging.ui.conversationlist.ConversationListItemView;
import com.android.messaging.util.Dates;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.Mockito;
@MediumTest
public class ConversationListItemViewTest extends ViewTest<ConversationListItemView> {
@Mock private ConversationListItemView.HostInterface mockHost;
private FakeCursor mCursor;
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
FakeFactory.register(context)
.withDataModel(new FakeDataModel(context))
.withUIIntents(new UIIntentsImpl());
mCursor = TestDataFactory.getConversationListCursor();
}
protected void verifyLaunchedConversationForId(final String id,
final ConversationListItemView conversationView) {
// Must be a short click.
final ArgumentMatcher<ConversationListItemData> itemDataIdMatcher =
new ArgumentMatcher<ConversationListItemData>() {
@Override
public boolean matches(final Object arg) {
return TextUtils.equals(id, ((ConversationListItemData) arg).getConversationId());
}
};
Mockito.verify(mockHost).onConversationClicked(
Mockito.argThat(itemDataIdMatcher), Mockito.eq(false),
Mockito.eq(conversationView));
}
protected void verifyContent(
final ConversationListItemView view, final FakeCursor cursor, final int index) {
/* ConversationQueryColumns.NAME */
final String conversationQueryColumnsName = "name";
final String name = (String) cursor.getAt(conversationQueryColumnsName, index);
/* ConversationQueryColumns.SNIPPET_TEXT */
final String conversationQueryColumnsSnippetText = "snippet_text";
final String snippet = (String) cursor.getAt(conversationQueryColumnsSnippetText, index);
/* ConversationQueryColumns.SORT_TIMESTAMP */
final String conversationQueryColumnsSortTimestamp = "sort_timestamp";
final String timestamp = Dates.getConversationTimeString(
(Long) cursor.getAt(conversationQueryColumnsSortTimestamp, index)).toString();
final boolean unread = !isRead(cursor, index);
verifyContent(view, name, snippet, timestamp, unread);
}
protected void verifyContent(
final ConversationListItemView view,
final String conversationName,
final String snippet,
final String timestamp,
final boolean unread) {
final TextView conversationNameView =
(TextView) view.findViewById(R.id.conversation_name);
final TextView snippetTextView = (TextView) view.findViewById(R.id.conversation_snippet);
final TextView timestampTextView = (TextView) view.findViewById(
R.id.conversation_timestamp);
final AsyncImageView imagePreviewView =
(AsyncImageView) view.findViewById(R.id.conversation_image_preview);
final Context context = Factory.get().getApplicationContext();
assertNotNull(conversationNameView);
assertEquals(conversationName, conversationNameView.getText());
assertNotNull(snippetTextView);
if (unread) {
assertEquals(ConversationListItemView.UNREAD_SNIPPET_LINE_COUNT,
snippetTextView.getMaxLines());
assertEquals(context.getResources().getColor(R.color.conversation_list_item_unread),
snippetTextView.getCurrentTextColor());
assertEquals(context.getResources().getColor(R.color.conversation_list_item_unread),
conversationNameView.getCurrentTextColor());
} else {
assertEquals(ConversationListItemView.NO_UNREAD_SNIPPET_LINE_COUNT,
snippetTextView.getMaxLines());
assertEquals(context.getResources().getColor(R.color.conversation_list_item_read),
snippetTextView.getCurrentTextColor());
assertEquals(context.getResources().getColor(R.color.conversation_list_item_read),
conversationNameView.getCurrentTextColor());
}
assertEquals(View.VISIBLE, imagePreviewView.getVisibility());
assertTrue(snippetTextView.getText().toString().contains(snippet));
assertEquals(timestamp, timestampTextView.getText());
}
protected boolean isRead(final FakeCursor cursor, final int index) {
return 1 == ((Integer) cursor.getAt("read", index)).intValue();
}
public void testBindUnread() {
final ConversationListItemView view = getView();
final int messageIndex = TestDataFactory.CONVERSATION_LIST_CURSOR_UNREAD_MESSAGE_INDEX;
mCursor.moveToPosition(messageIndex);
assertFalse(isRead(mCursor, messageIndex));
view.bind(mCursor, mockHost);
verifyContent(view, mCursor, messageIndex);
}
public void testBindRead() {
final ConversationListItemView view = getView();
final int messageIndex = TestDataFactory.CONVERSATION_LIST_CURSOR_READ_MESSAGE_INDEX;
mCursor.moveToPosition(messageIndex);
assertTrue(isRead(mCursor, messageIndex));
view.bind(mCursor, mockHost);
verifyContent(view, mCursor, messageIndex);
}
public void testClickLaunchesConversation() {
final ConversationListItemView view = getView();
final View swipeableContainer = view.findViewById(R.id.swipeableContainer);
mCursor.moveToFirst();
view.bind(mCursor, mockHost);
swipeableContainer.performClick();
verifyLaunchedConversationForId(
mCursor.getAt("_id" /* ConversationQueryColumns._ID */, 0).toString(), view);
}
public void testBindTwice() {
final ConversationListItemView view = getView();
mCursor.moveToFirst();
view.bind(mCursor, mockHost);
mCursor.moveToNext();
view.bind(mCursor, mockHost);
verifyContent(view, mCursor, mCursor.getPosition());
}
@Override
protected int getLayoutIdForView() {
return R.layout.conversation_list_item_view;
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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.mediapicker;
import android.media.MediaPlayer;
import android.media.MediaRecorder.OnErrorListener;
import android.media.MediaRecorder.OnInfoListener;
import android.net.Uri;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.ui.ViewTest;
import com.android.messaging.util.FakeMediaUtil;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
public class AudioRecordViewTest extends ViewTest<AudioRecordView> {
@Mock AudioRecordView.HostInterface mockHost;
@Mock LevelTrackingMediaRecorder mockRecorder;
@Mock MediaPlayer mockMediaPlayer;
@Override
protected void setUp() throws Exception {
super.setUp();
FakeFactory.register(getInstrumentation().getContext())
.withMediaUtil(new FakeMediaUtil(mockMediaPlayer));
}
private void verifyAudioSubmitted() {
Mockito.verify(mockHost).onAudioRecorded(Matchers.any(MessagePartData.class));
}
private AudioRecordView initView() {
final AudioRecordView view = getView();
view.testSetMediaRecorder(mockRecorder);
view.setHostInterface(mockHost);
return view;
}
public void testRecording() {
Mockito.when(mockRecorder.isRecording()).thenReturn(false);
Mockito.when(mockRecorder.startRecording(Matchers.<OnErrorListener>any(),
Matchers.<OnInfoListener>any(), Matchers.anyInt())).thenReturn(true);
Mockito.when(mockRecorder.stopRecording()).thenReturn(Uri.parse("content://someaudio/2"));
final AudioRecordView view = initView();
view.onRecordButtonTouchDown();
Mockito.verify(mockRecorder).startRecording(Matchers.<OnErrorListener>any(),
Matchers.<OnInfoListener>any(), Matchers.anyInt());
Mockito.when(mockRecorder.isRecording()).thenReturn(true);
// Record for 1 second to make it meaningful.
sleepNoThrow(1000);
view.onRecordButtonTouchUp();
// We added some buffer to the end of the audio recording, so sleep for sometime and
// verify audio is recorded.
sleepNoThrow(700);
Mockito.verify(mockRecorder).stopRecording();
verifyAudioSubmitted();
}
private void sleepNoThrow(final long duration) {
try {
Thread.sleep(duration);
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
}
}
@Override
protected int getLayoutIdForView() {
return R.layout.mediapicker_audio_chooser;
}
}

View File

@@ -0,0 +1,154 @@
/*
* 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.mediapicker;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.os.AsyncTask;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.messaging.BugleTestCase;
import com.android.messaging.ui.mediapicker.CameraManager.CameraWrapper;
import org.mockito.InOrder;
import org.mockito.Mockito;
@SmallTest
public class CameraManagerTest extends BugleTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
// Force each test to set up a camera wrapper to match their needs
CameraManager.setCameraWrapper(null);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
MockCameraFactory.cleanup();
}
public void testNoCameraDeviceGetInfo() {
CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper());
assertEquals(false, CameraManager.get().hasAnyCamera());
assertEquals(false, CameraManager.get().hasFrontAndBackCamera());
try {
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
fail("selectCamera should have thrown");
} catch (AssertionError e) {
}
}
public void testFrontFacingOnlyGetInfo() {
CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT)
));
assertEquals(true, CameraManager.get().hasAnyCamera());
assertEquals(false, CameraManager.get().hasFrontAndBackCamera());
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
}
public void testBackFacingOnlyGetInfo() {
CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK)
));
assertEquals(true, CameraManager.get().hasAnyCamera());
assertEquals(false, CameraManager.get().hasFrontAndBackCamera());
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
}
public void testFrontAndBackGetInfo() {
CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT),
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK)
));
assertEquals(true, CameraManager.get().hasAnyCamera());
assertEquals(true, CameraManager.get().hasFrontAndBackCamera());
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
}
public void testSwapCamera() {
CameraManager.setCameraWrapper(MockCameraFactory.createCameraWrapper(
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT),
MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK)
));
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_FRONT);
assertEquals(CameraInfo.CAMERA_FACING_FRONT, CameraManager.get().getCameraInfo().facing);
CameraManager.get().swapCamera();
assertEquals(CameraInfo.CAMERA_FACING_BACK, CameraManager.get().getCameraInfo().facing);
}
public void testOpenCamera() {
Camera backCamera = MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_BACK);
Camera frontCamera = MockCameraFactory.createCamera(CameraInfo.CAMERA_FACING_FRONT);
CameraWrapper wrapper = MockCameraFactory.createCameraWrapper(frontCamera, backCamera);
CameraManager.setCameraWrapper(wrapper);
CameraManager.get().selectCamera(CameraInfo.CAMERA_FACING_BACK);
CameraManager.get().openCamera();
CameraManager.get().openCamera();
CameraManager.get().openCamera();
waitForPendingAsyncTasks();
Mockito.verify(wrapper, Mockito.never()).open(0);
Mockito.verify(wrapper).open(1);
Mockito.verify(wrapper, Mockito.never()).release(frontCamera);
Mockito.verify(wrapper, Mockito.never()).release(backCamera);
CameraManager.get().swapCamera();
waitForPendingAsyncTasks();
Mockito.verify(wrapper).open(0);
Mockito.verify(wrapper).open(1);
Mockito.verify(wrapper, Mockito.never()).release(frontCamera);
Mockito.verify(wrapper).release(backCamera);
InOrder inOrder = Mockito.inOrder(wrapper);
inOrder.verify(wrapper).open(1);
inOrder.verify(wrapper).release(backCamera);
inOrder.verify(wrapper).open(0);
}
private void waitForPendingAsyncTasks() {
try {
final Object lockObject = new Object();
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
synchronized (lockObject) {
lockObject.notifyAll();
}
}
}.execute();
synchronized (lockObject) {
lockObject.wait(500);
}
} catch (InterruptedException e) {
fail();
}
}
}

View File

@@ -0,0 +1,145 @@
/*
* 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.mediapicker;
import android.content.Context;
import android.provider.MediaStore.Images.Media;
import android.view.View;
import android.widget.CheckBox;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeCursor;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.data.GalleryGridItemData;
import com.android.messaging.datamodel.data.TestDataFactory;
import com.android.messaging.ui.AsyncImageView;
import com.android.messaging.ui.ViewTest;
import com.android.messaging.util.UriUtil;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
public class GalleryGridItemViewTest extends ViewTest<GalleryGridItemView> {
@Mock GalleryGridItemView.HostInterface mockHost;
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
FakeFactory.register(context)
.withDataModel(new FakeDataModel(context));
}
protected void verifyClickedItem(final View view, final GalleryGridItemData data) {
Mockito.verify(mockHost).onItemClicked(view, data, false /* longClick */);
}
protected void verifyContent(
final GalleryGridItemView view,
final String imageUrl,
final boolean showCheckbox,
final boolean isSelected) {
final AsyncImageView imageView = (AsyncImageView) view.findViewById(R.id.image);
final CheckBox checkBox = (CheckBox) view.findViewById(R.id.checkbox);
assertNotNull(imageView);
assertTrue(imageView.mImageRequestBinding.isBound());
assertTrue(imageView.mImageRequestBinding.getData().getKey().startsWith(imageUrl));
assertNotNull(checkBox);
if (showCheckbox) {
assertEquals(View.VISIBLE, checkBox.getVisibility());
assertEquals(isSelected, checkBox.isChecked());
} else {
assertNotSame(View.VISIBLE, checkBox.getVisibility());
}
}
public void testBind() {
Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(false);
Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
.thenReturn(false);
final GalleryGridItemView view = getView();
final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
cursor.moveToFirst();
final String path = (String) cursor.getAt(Media.DATA, 0);
view.bind(cursor, mockHost);
verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
false, false);
}
public void testBindMultiSelectUnSelected() {
Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(true);
Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
.thenReturn(false);
final GalleryGridItemView view = getView();
final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
cursor.moveToFirst();
final String path = (String) cursor.getAt(Media.DATA, 0);
view.bind(cursor, mockHost);
verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
true, false);
}
public void testBindMultiSelectSelected() {
Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(true);
Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
.thenReturn(true);
final GalleryGridItemView view = getView();
final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
cursor.moveToFirst();
final String path = (String) cursor.getAt(Media.DATA, 0);
view.bind(cursor, mockHost);
verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
true, true);
}
public void testClick() {
Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(false);
Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
.thenReturn(false);
final GalleryGridItemView view = getView();
final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
cursor.moveToFirst();
view.bind(cursor, mockHost);
view.performClick();
verifyClickedItem(view, view.mData);
}
public void testBindTwice() {
Mockito.when(mockHost.isMultiSelectEnabled()).thenReturn(true);
Mockito.when(mockHost.isItemSelected(Matchers.<GalleryGridItemData>any()))
.thenReturn(false);
final GalleryGridItemView view = getView();
final FakeCursor cursor = TestDataFactory.getGalleryGridCursor();
cursor.moveToFirst();
view.bind(cursor, mockHost);
cursor.moveToNext();
final String path = (String) cursor.getAt(Media.DATA, 1);
view.bind(cursor, mockHost);
verifyContent(view, UriUtil.getUriForResourceFile(path).toString(),
true, false);
}
@Override
protected int getLayoutIdForView() {
return R.layout.gallery_grid_item_view;
}
}

View File

@@ -0,0 +1,129 @@
/*
* 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.mediapicker;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import com.android.messaging.FakeFactory;
import com.android.messaging.R;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.binding.Binding;
import com.android.messaging.datamodel.binding.BindingBase;
import com.android.messaging.datamodel.data.DraftMessageData;
import com.android.messaging.datamodel.data.MediaPickerData;
import com.android.messaging.ui.FragmentTestCase;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
public class MediaPickerTest extends FragmentTestCase<MediaPicker> {
@Mock protected MediaPickerData mMockMediaPickerData;
@Mock protected DraftMessageData mMockDraftMessageData;
protected FakeDataModel mFakeDataModel;
public MediaPickerTest() {
super(MediaPicker.class);
}
@Override
protected MediaPicker getFragment() {
if (mFragment == null) {
mFragment = new MediaPicker(getInstrumentation().getTargetContext());
}
return mFragment;
}
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
mFakeDataModel = new FakeDataModel(context)
.withMediaPickerData(mMockMediaPickerData);
FakeFactory.register(context)
.withDataModel(mFakeDataModel);
}
/**
* Helper method to initialize the MediaPicker and its data.
*/
private void initFragment(final int supportedMediaTypes, final Integer[] expectedLoaderIds,
final boolean filterTabBeforeAttach) {
Mockito.when(mMockMediaPickerData.isBound(Matchers.anyString()))
.thenReturn(true);
Mockito.when(mMockDraftMessageData.isBound(Matchers.anyString()))
.thenReturn(true);
final Binding<DraftMessageData> draftBinding = BindingBase.createBinding(this);
draftBinding.bind(mMockDraftMessageData);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
final MediaPicker fragment = getFragment();
if (filterTabBeforeAttach) {
fragment.setSupportedMediaTypes(supportedMediaTypes);
getActivity().setFragment(fragment);
} else {
getActivity().setFragment(fragment);
fragment.setSupportedMediaTypes(supportedMediaTypes);
}
fragment.setDraftMessageDataModel(draftBinding);
Mockito.verify(mMockMediaPickerData,
Mockito.atLeastOnce()).init(
Matchers.eq(fragment.getLoaderManager()));
fragment.open(MediaPicker.MEDIA_TYPE_ALL, false);
}
});
getInstrumentation().waitForIdleSync();
}
public void testDefaultTabs() {
Mockito.when(mMockMediaPickerData.getSelectedChooserIndex()).thenReturn(0);
initFragment(MediaPicker.MEDIA_TYPE_ALL, new Integer[] {
MediaPickerData.GALLERY_IMAGE_LOADER },
false);
final MediaPicker mediaPicker = getFragment();
final View view = mediaPicker.getView();
assertNotNull(view);
final ViewGroup tabStrip = (ViewGroup) view.findViewById(R.id.mediapicker_tabstrip);
assertEquals(tabStrip.getChildCount(), 3);
for (int i = 0; i < tabStrip.getChildCount(); i++) {
final ImageButton tabButton = (ImageButton) tabStrip.getChildAt(i);
assertEquals(View.VISIBLE, tabButton.getVisibility());
assertEquals(i == 0, tabButton.isSelected());
}
}
public void testFilterTabsBeforeAttach() {
Mockito.when(mMockMediaPickerData.getSelectedChooserIndex()).thenReturn(0);
initFragment(MediaPicker.MEDIA_TYPE_IMAGE, new Integer[] {
MediaPickerData.GALLERY_IMAGE_LOADER },
true);
final MediaPicker mediaPicker = getFragment();
final View view = mediaPicker.getView();
assertNotNull(view);
final ViewGroup tabStrip = (ViewGroup) view.findViewById(R.id.mediapicker_tabstrip);
assertEquals(tabStrip.getChildCount(), 3);
for (int i = 0; i < tabStrip.getChildCount(); i++) {
final ImageButton tabButton = (ImageButton) tabStrip.getChildAt(i);
assertEquals(i == 0, tabButton.isSelected());
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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.mediapicker;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import com.android.messaging.ui.mediapicker.CameraManager.CameraWrapper;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.util.HashMap;
import java.util.Map;
class MockCameraFactory {
private static Map<Camera, CameraInfo> sCameraInfos = new HashMap<Camera, CameraInfo>();
public static Camera createCamera(int facing) {
Camera camera = Mockito.mock(Camera.class);
CameraInfo cameraInfo = new CameraInfo();
cameraInfo.facing = facing;
sCameraInfos.put(camera, cameraInfo);
return camera;
}
public static void getCameraInfo(Camera camera, CameraInfo outCameraInfo) {
CameraInfo cameraInfo = sCameraInfos.get(camera);
outCameraInfo.facing = cameraInfo.facing;
outCameraInfo.orientation = cameraInfo.orientation;
outCameraInfo.canDisableShutterSound = cameraInfo.canDisableShutterSound;
}
public static CameraWrapper createCameraWrapper(final Camera... cameras) {
CameraWrapper wrapper = Mockito.mock(CameraWrapper.class);
Mockito.when(wrapper.getNumberOfCameras()).thenReturn(cameras.length);
Mockito.when(wrapper.open(Mockito.anyInt())).then(new Answer<Camera>() {
@Override
public Camera answer(InvocationOnMock invocation) {
return cameras[(Integer) invocation.getArguments()[0]];
}
});
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
getCameraInfo(
cameras[(Integer) invocation.getArguments()[0]],
(CameraInfo) invocation.getArguments()[1]
);
return null;
}
}).when(wrapper).getCameraInfo(Mockito.anyInt(), Mockito.any(CameraInfo.class));
return wrapper;
}
public static void cleanup() {
sCameraInfos.clear();
}
}