1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.messaging.ui.attachmentchooser;
18 
19 import android.app.Fragment;
20 import android.test.suitebuilder.annotation.LargeTest;
21 import android.widget.CheckBox;
22 
23 import com.android.messaging.FakeFactory;
24 import com.android.messaging.R;
25 import com.android.messaging.datamodel.DataModel;
26 import com.android.messaging.datamodel.data.DraftMessageData;
27 import com.android.messaging.datamodel.data.MessageData;
28 import com.android.messaging.datamodel.data.MessagePartData;
29 import com.android.messaging.datamodel.data.TestDataFactory;
30 import com.android.messaging.ui.FragmentTestCase;
31 import com.android.messaging.ui.TestActivity;
32 import com.android.messaging.ui.TestActivity.FragmentEventListener;
33 import com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment;
34 import com.android.messaging.ui.attachmentchooser.AttachmentGridItemView;
35 import com.android.messaging.ui.attachmentchooser.AttachmentGridView;
36 import com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment.AttachmentChooserFragmentHost;
37 import com.android.messaging.ui.conversationlist.ConversationListFragment;
38 
39 import org.mockito.Matchers;
40 import org.mockito.Mock;
41 import org.mockito.Mockito;
42 import org.mockito.compat.ArgumentMatcher;
43 
44 import java.util.Arrays;
45 import java.util.HashSet;
46 import java.util.List;
47 import java.util.Set;
48 
49 
50 /**
51  * Unit tests for {@link ConversationListFragment}.
52  */
53 @LargeTest
54 public class AttachmentChooserFragmentTest extends FragmentTestCase<AttachmentChooserFragment> {
55 
56     @Mock protected DataModel mockDataModel;
57     @Mock protected DraftMessageData mockDraftMessageData;
58     @Mock protected AttachmentChooserFragmentHost mockHost;
59 
60     private static final String CONVERSATION_ID = "cid";
61 
62     /** A custom argument matcher that checks whether the set argument passed in is a set
63      * with identical attachment data as the given set.
64      */
65     private class IsSetOfGivenAttachments extends ArgumentMatcher<Set<MessagePartData>> {
66         private final Set<MessagePartData> mGivenParts;
IsSetOfGivenAttachments(final Set<MessagePartData> givenParts)67         public IsSetOfGivenAttachments(final Set<MessagePartData> givenParts) {
68             mGivenParts = givenParts;
69         }
70 
71         @Override
matchesObject(final Object set)72         public boolean matchesObject(final Object set) {
73             @SuppressWarnings("unchecked")
74             final Set<MessagePartData> actualSet = (Set<MessagePartData>) set;
75             if (actualSet.size() != mGivenParts.size()) {
76                 return false;
77             }
78             return mGivenParts.containsAll(actualSet) && actualSet.containsAll(mGivenParts);
79         }
80      }
81 
AttachmentChooserFragmentTest()82     public AttachmentChooserFragmentTest() {
83         super(AttachmentChooserFragment.class);
84     }
85 
86     @Override
setUp()87     protected void setUp() throws Exception {
88         super.setUp();
89         FakeFactory.register(this.getInstrumentation().getTargetContext())
90             .withDataModel(mockDataModel);
91     }
92 
loadWith(final List<MessagePartData> attachments)93     private void loadWith(final List<MessagePartData> attachments) {
94         Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
95             .thenReturn(true);
96         Mockito.doReturn(mockDraftMessageData)
97             .when(mockDataModel)
98             .createDraftMessageData(Mockito.anyString());
99         Mockito.doReturn(attachments)
100             .when(mockDraftMessageData)
101             .getReadOnlyAttachments();
102         Mockito.when(mockDataModel.createDraftMessageData(
103                 Matchers.anyString()))
104             .thenReturn(mockDraftMessageData);
105 
106         // Create fragment synchronously to avoid need for volatile, synchronization etc.
107         final AttachmentChooserFragment fragment = getFragment();
108         // Binding to model happens when attaching fragment to activity, so hook into test
109         // activity to do so.
110         getActivity().setFragmentEventListener(new FragmentEventListener() {
111             @Override
112             public void onAttachFragment(final Fragment attachedFragment) {
113                 if (fragment == attachedFragment) {
114                     fragment.setConversationId(CONVERSATION_ID);
115                 }
116             }
117         });
118 
119         getActivity().runOnUiThread(new Runnable() {
120             @Override
121             public void run() {
122                 fragment.setHost(mockHost);
123                 getActivity().setFragment(fragment);
124                 Mockito.verify(mockDataModel).createDraftMessageData(
125                         Mockito.matches(CONVERSATION_ID));
126                 Mockito.verify(mockDraftMessageData).loadFromStorage(
127                         Matchers.eq(fragment.mBinding), Matchers.eq((MessageData) null),
128                         Matchers.eq(false));
129             }
130         });
131         // Now load the cursor
132         getActivity().runOnUiThread(new Runnable() {
133             @Override
134             public void run() {
135                 fragment.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
136             }
137         });
138         getInstrumentation().waitForIdleSync();
139     }
140 
testUnselect()141     public void testUnselect() {
142         final List<MessagePartData> attachments = TestDataFactory.getTestDraftAttachments();
143         loadWith(attachments);
144         final AttachmentGridView attachmentGridView = (AttachmentGridView)
145                 getFragment().getView().findViewById(R.id.grid);
146         assertEquals("bad view count", attachments.size(),
147                 attachmentGridView.getAdapter().getCount());
148 
149         final AttachmentGridItemView itemView = (AttachmentGridItemView)
150                 attachmentGridView.getChildAt(0);
151         assertEquals(attachmentGridView, itemView.testGetHostInterface());
152         final CheckBox checkBox = (CheckBox) itemView.findViewById(R.id.checkbox);
153         assertEquals(true, checkBox.isChecked());
154         assertEquals(true, attachmentGridView.isItemSelected(itemView.mAttachmentData));
155         clickButton(checkBox);
156         assertEquals(false, checkBox.isChecked());
157         assertEquals(false, attachmentGridView.isItemSelected(itemView.mAttachmentData));
158 
159         final AttachmentGridItemView itemView2 = (AttachmentGridItemView)
160                 attachmentGridView.getChildAt(1);
161         final CheckBox checkBox2 = (CheckBox) itemView2.findViewById(R.id.checkbox);
162         clickButton(checkBox2);
163 
164         getFragment().confirmSelection();
165         final MessagePartData[] attachmentsToRemove = new MessagePartData[] {
166                 itemView.mAttachmentData, itemView2.mAttachmentData };
167         Mockito.verify(mockDraftMessageData).removeExistingAttachments(Matchers.argThat(
168                 new IsSetOfGivenAttachments(new HashSet<>(Arrays.asList(attachmentsToRemove)))));
169         Mockito.verify(mockDraftMessageData).saveToStorage(Matchers.eq(getFragment().mBinding));
170         Mockito.verify(mockHost).onConfirmSelection();
171     }
172 }
173