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.widget.CheckBox;
21 
22 import androidx.test.filters.LargeTest;
23 
24 import com.android.messaging.FakeFactory;
25 import com.android.messaging.R;
26 import com.android.messaging.datamodel.DataModel;
27 import com.android.messaging.datamodel.data.DraftMessageData;
28 import com.android.messaging.datamodel.data.MessageData;
29 import com.android.messaging.datamodel.data.MessagePartData;
30 import com.android.messaging.datamodel.data.TestDataFactory;
31 import com.android.messaging.ui.FragmentTestCase;
32 import com.android.messaging.ui.TestActivity.FragmentEventListener;
33 import com.android.messaging.ui.attachmentchooser.AttachmentChooserFragment.AttachmentChooserFragmentHost;
34 import com.android.messaging.ui.conversationlist.ConversationListFragment;
35 
36 import org.mockito.ArgumentMatcher;
37 import org.mockito.Matchers;
38 import org.mockito.Mock;
39 import org.mockito.Mockito;
40 
41 import java.util.Arrays;
42 import java.util.HashSet;
43 import java.util.List;
44 import java.util.Set;
45 
46 /**
47  * Unit tests for {@link ConversationListFragment}.
48  */
49 @LargeTest
50 public class AttachmentChooserFragmentTest extends FragmentTestCase<AttachmentChooserFragment> {
51 
52     @Mock protected DataModel mockDataModel;
53     @Mock protected DraftMessageData mockDraftMessageData;
54     @Mock protected AttachmentChooserFragmentHost mockHost;
55 
56     private static final String CONVERSATION_ID = "cid";
57 
58     /** A custom argument matcher that checks whether the set argument passed in is a set
59      * with identical attachment data as the given set.
60      */
61     private class IsSetOfGivenAttachments implements ArgumentMatcher<Set<MessagePartData>> {
62         private final Set<MessagePartData> mGivenParts;
IsSetOfGivenAttachments(final Set<MessagePartData> givenParts)63         public IsSetOfGivenAttachments(final Set<MessagePartData> givenParts) {
64             mGivenParts = givenParts;
65         }
66 
67         @Override
matches(final Set<MessagePartData> actualSet)68         public boolean matches(final Set<MessagePartData> actualSet) {
69             if (actualSet.size() != mGivenParts.size()) {
70                 return false;
71             }
72             return mGivenParts.containsAll(actualSet) && actualSet.containsAll(mGivenParts);
73         }
74      }
75 
AttachmentChooserFragmentTest()76     public AttachmentChooserFragmentTest() {
77         super(AttachmentChooserFragment.class);
78     }
79 
80     @Override
setUp()81     protected void setUp() throws Exception {
82         super.setUp();
83         FakeFactory.register(this.getInstrumentation().getTargetContext())
84             .withDataModel(mockDataModel);
85     }
86 
loadWith(final List<MessagePartData> attachments)87     private void loadWith(final List<MessagePartData> attachments) {
88         Mockito.when(mockDraftMessageData.isBound(Matchers.anyString()))
89             .thenReturn(true);
90         Mockito.doReturn(mockDraftMessageData)
91             .when(mockDataModel)
92             .createDraftMessageData(Mockito.anyString());
93         Mockito.doReturn(attachments)
94             .when(mockDraftMessageData)
95             .getReadOnlyAttachments();
96         Mockito.when(mockDataModel.createDraftMessageData(
97                 Matchers.anyString()))
98             .thenReturn(mockDraftMessageData);
99 
100         // Create fragment synchronously to avoid need for volatile, synchronization etc.
101         final AttachmentChooserFragment fragment = getFragment();
102         // Binding to model happens when attaching fragment to activity, so hook into test
103         // activity to do so.
104         getActivity().setFragmentEventListener(new FragmentEventListener() {
105             @Override
106             public void onAttachFragment(final Fragment attachedFragment) {
107                 if (fragment == attachedFragment) {
108                     fragment.setConversationId(CONVERSATION_ID);
109                 }
110             }
111         });
112 
113         getActivity().runOnUiThread(new Runnable() {
114             @Override
115             public void run() {
116                 fragment.setHost(mockHost);
117                 getActivity().setFragment(fragment);
118                 Mockito.verify(mockDataModel).createDraftMessageData(
119                         Mockito.matches(CONVERSATION_ID));
120                 Mockito.verify(mockDraftMessageData).loadFromStorage(
121                         Matchers.eq(fragment.mBinding), Matchers.eq((MessageData) null),
122                         Matchers.eq(false));
123             }
124         });
125         // Now load the cursor
126         getActivity().runOnUiThread(new Runnable() {
127             @Override
128             public void run() {
129                 fragment.onDraftChanged(mockDraftMessageData, DraftMessageData.ALL_CHANGED);
130             }
131         });
132         getInstrumentation().waitForIdleSync();
133     }
134 
testUnselect()135     public void testUnselect() {
136         final List<MessagePartData> attachments = TestDataFactory.getTestDraftAttachments();
137         loadWith(attachments);
138         final AttachmentGridView attachmentGridView = (AttachmentGridView)
139                 getFragment().getView().findViewById(R.id.grid);
140         assertEquals("bad view count", attachments.size(),
141                 attachmentGridView.getAdapter().getCount());
142 
143         final AttachmentGridItemView itemView = (AttachmentGridItemView)
144                 attachmentGridView.getChildAt(0);
145         assertEquals(attachmentGridView, itemView.testGetHostInterface());
146         final CheckBox checkBox = (CheckBox) itemView.findViewById(R.id.checkbox);
147         assertEquals(true, checkBox.isChecked());
148         assertEquals(true, attachmentGridView.isItemSelected(itemView.mAttachmentData));
149         clickButton(checkBox);
150         assertEquals(false, checkBox.isChecked());
151         assertEquals(false, attachmentGridView.isItemSelected(itemView.mAttachmentData));
152 
153         final AttachmentGridItemView itemView2 = (AttachmentGridItemView)
154                 attachmentGridView.getChildAt(1);
155         final CheckBox checkBox2 = (CheckBox) itemView2.findViewById(R.id.checkbox);
156         clickButton(checkBox2);
157 
158         getFragment().confirmSelection();
159         final MessagePartData[] attachmentsToRemove = new MessagePartData[] {
160                 itemView.mAttachmentData, itemView2.mAttachmentData };
161         Mockito.verify(mockDraftMessageData).removeExistingAttachments(Matchers.argThat(
162                 new IsSetOfGivenAttachments(new HashSet<>(Arrays.asList(attachmentsToRemove)))));
163         Mockito.verify(mockDraftMessageData).saveToStorage(Matchers.eq(getFragment().mBinding));
164         Mockito.verify(mockHost).onConfirmSelection();
165     }
166 }
167