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 android.view.cts;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertSame;
24 import static org.junit.Assert.assertTrue;
25 import static org.mockito.Matchers.any;
26 import static org.mockito.Mockito.atLeastOnce;
27 import static org.mockito.Mockito.doReturn;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.never;
30 import static org.mockito.Mockito.spy;
31 import static org.mockito.Mockito.verify;
32 
33 import android.Manifest;
34 import android.app.Instrumentation;
35 import android.graphics.Rect;
36 import android.platform.test.annotations.AppModeSdkSandbox;
37 import android.view.ActionMode;
38 import android.view.Menu;
39 import android.view.MenuInflater;
40 import android.view.View;
41 
42 import androidx.test.InstrumentationRegistry;
43 import androidx.test.filters.SmallTest;
44 import androidx.test.rule.ActivityTestRule;
45 import androidx.test.runner.AndroidJUnit4;
46 
47 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
48 
49 import org.junit.Before;
50 import org.junit.Rule;
51 import org.junit.Test;
52 import org.junit.runner.RunWith;
53 
54 @SmallTest
55 @RunWith(AndroidJUnit4.class)
56 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).")
57 public class ActionModeTest {
58     private Instrumentation mInstrumentation;
59     private ActionModeCtsActivity mActivity;
60 
61     @Rule(order = 0)
62     public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
63             androidx.test.platform.app.InstrumentationRegistry
64                     .getInstrumentation().getUiAutomation(),
65             Manifest.permission.START_ACTIVITIES_FROM_SDK_SANDBOX);
66 
67     @Rule(order = 1)
68     public ActivityTestRule<ActionModeCtsActivity> mActivityRule =
69             new ActivityTestRule<>(ActionModeCtsActivity.class);
70 
71     @Before
setup()72     public void setup() {
73         mInstrumentation = InstrumentationRegistry.getInstrumentation();
74         mActivity = mActivityRule.getActivity();
75     }
76 
77     @Test
testSetType()78     public void testSetType() {
79         final ActionMode mockActionMode = new MockActionMode();
80         assertEquals(ActionMode.TYPE_PRIMARY, mockActionMode.getType());
81 
82         mockActionMode.setType(ActionMode.TYPE_FLOATING);
83         assertEquals(ActionMode.TYPE_FLOATING, mockActionMode.getType());
84 
85         mockActionMode.setType(ActionMode.TYPE_PRIMARY);
86         assertEquals(ActionMode.TYPE_PRIMARY, mockActionMode.getType());
87     }
88 
89     @Test
testInvalidateContentRectDoesNotInvalidateFull()90     public void testInvalidateContentRectDoesNotInvalidateFull() {
91         final ActionMode mockActionMode = spy(new MockActionMode());
92 
93         mockActionMode.invalidateContentRect();
94 
95         verify(mockActionMode, never()).invalidate();
96     }
97 
98     @Test
testInvalidateContentRectOnFloatingCallsCallback()99     public void testInvalidateContentRectOnFloatingCallsCallback() throws Throwable {
100         final View view = mActivity.contentView;
101         final ActionMode.Callback2 mockCallback = mock(ActionMode.Callback2.class);
102         doReturn(Boolean.TRUE).when(mockCallback).onCreateActionMode(
103                 any(ActionMode.class), any(Menu.class));
104         doReturn(Boolean.TRUE).when(mockCallback).onPrepareActionMode(
105                 any(ActionMode.class), any(Menu.class));
106 
107         mActivityRule.runOnUiThread(() -> {
108             ActionMode mode = view.startActionMode(mockCallback, ActionMode.TYPE_FLOATING);
109             assertNotNull(mode);
110             mode.invalidateContentRect();
111         });
112         mInstrumentation.waitForIdleSync();
113 
114         verify(mockCallback, atLeastOnce()).onGetContentRect(any(ActionMode.class), any(View.class),
115                 any(Rect.class));
116     }
117 
118     @Test
testSetAndGetTitleOptionalHint()119     public void testSetAndGetTitleOptionalHint() {
120         final ActionMode actionMode = new MockActionMode();
121 
122         // Check default value.
123         assertFalse(actionMode.getTitleOptionalHint());
124         // Test set and get.
125         actionMode.setTitleOptionalHint(true);
126         assertTrue(actionMode.getTitleOptionalHint());
127         actionMode.setTitleOptionalHint(false);
128         assertFalse(actionMode.getTitleOptionalHint());
129     }
130 
131     @Test
testSetAndGetTag()132     public void testSetAndGetTag() {
133         final ActionMode actionMode = new MockActionMode();
134         Object tag = new Object();
135 
136         // Check default value.
137         assertNull(actionMode.getTag());
138 
139         actionMode.setTag(tag);
140         assertSame(tag, actionMode.getTag());
141     }
142 
143     @Test
testIsTitleOptional()144     public void testIsTitleOptional() {
145         final ActionMode actionMode = new MockActionMode();
146 
147         // Check default value.
148         assertFalse(actionMode.isTitleOptional());
149     }
150 
151     @Test
testIsUiFocusable()152     public void testIsUiFocusable() {
153         final ActionMode actionMode = new MockActionMode();
154 
155         // Check default value.
156         assertTrue(actionMode.isUiFocusable());
157     }
158 
159     @Test
testHide()160     public void testHide() {
161         final ActionMode actionMode = new MockActionMode();
162 
163         actionMode.hide(0);
164         actionMode.hide(ActionMode.DEFAULT_HIDE_DURATION);
165     }
166 
167     @Test
testOnWindowFocusChanged()168     public void testOnWindowFocusChanged() {
169         final ActionMode actionMode = new MockActionMode();
170 
171         actionMode.onWindowFocusChanged(true);
172         actionMode.onWindowFocusChanged(false);
173     }
174 
175     protected static class MockActionMode extends ActionMode {
176         @Override
setTitle(CharSequence title)177         public void setTitle(CharSequence title) {}
178 
179         @Override
setTitle(int resId)180         public void setTitle(int resId) {}
181 
182         @Override
setSubtitle(CharSequence subtitle)183         public void setSubtitle(CharSequence subtitle) {}
184 
185         @Override
setSubtitle(int resId)186         public void setSubtitle(int resId) {}
187 
188         @Override
setCustomView(View view)189         public void setCustomView(View view) {}
190 
191         @Override
invalidate()192         public void invalidate() {
193         }
194 
195         @Override
finish()196         public void finish() {}
197 
198         @Override
getMenu()199         public Menu getMenu() {
200             return null;
201         }
202 
203         @Override
getTitle()204         public CharSequence getTitle() {
205             return null;
206         }
207 
208         @Override
getSubtitle()209         public CharSequence getSubtitle() {
210             return null;
211         }
212 
213         @Override
getCustomView()214         public View getCustomView() {
215             return null;
216         }
217 
218         @Override
getMenuInflater()219         public MenuInflater getMenuInflater() {
220             return null;
221         }
222     }
223 }
224