Home | History | Annotate | Download | only in app
      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 androidx.appcompat.app;
     18 
     19 import static android.support.test.espresso.Espresso.onView;
     20 import static android.support.test.espresso.matcher.ViewMatchers.withId;
     21 
     22 import static androidx.appcompat.testutils.TestUtilsActions.setSystemUiVisibility;
     23 
     24 import static org.junit.Assert.assertEquals;
     25 import static org.junit.Assert.assertNotNull;
     26 import static org.junit.Assert.assertNull;
     27 import static org.junit.Assert.assertTrue;
     28 import static org.mockito.Matchers.any;
     29 import static org.mockito.Matchers.eq;
     30 import static org.mockito.Mockito.atLeastOnce;
     31 import static org.mockito.Mockito.mock;
     32 import static org.mockito.Mockito.never;
     33 import static org.mockito.Mockito.reset;
     34 import static org.mockito.Mockito.spy;
     35 import static org.mockito.Mockito.verify;
     36 import static org.mockito.Mockito.verifyNoMoreInteractions;
     37 import static org.mockito.Mockito.when;
     38 
     39 import android.annotation.SuppressLint;
     40 import android.app.Activity;
     41 import android.content.pm.PackageManager;
     42 import android.support.test.annotation.UiThreadTest;
     43 import android.support.test.filters.SdkSuppress;
     44 import android.support.test.filters.SmallTest;
     45 import android.support.test.rule.ActivityTestRule;
     46 import android.support.test.runner.AndroidJUnit4;
     47 import android.view.Menu;
     48 import android.view.View;
     49 import android.view.WindowInsets;
     50 
     51 import androidx.annotation.RequiresApi;
     52 import androidx.appcompat.custom.FitWindowsContentLayout;
     53 import androidx.appcompat.test.R;
     54 import androidx.appcompat.testutils.BaseTestActivity;
     55 import androidx.appcompat.view.ActionMode;
     56 
     57 import org.junit.Rule;
     58 import org.junit.Test;
     59 import org.junit.runner.RunWith;
     60 
     61 @SmallTest
     62 @RunWith(AndroidJUnit4.class)
     63 public abstract class BaseBasicsTestCase<A extends BaseTestActivity> {
     64     @Rule
     65     public final ActivityTestRule<A> mActivityTestRule;
     66 
     67 
     68     protected BaseBasicsTestCase(Class<A> activityClass) {
     69         mActivityTestRule = new ActivityTestRule<>(activityClass);
     70     }
     71 
     72     @Test
     73     public void testActionBarExists() {
     74         assertNotNull("ActionBar is not null",
     75                 mActivityTestRule.getActivity().getSupportActionBar());
     76     }
     77 
     78     @Test
     79     public void testDefaultActionBarTitle() {
     80         assertEquals(mActivityTestRule.getActivity().getTitle(),
     81                 mActivityTestRule.getActivity().getSupportActionBar().getTitle());
     82     }
     83 
     84     @UiThreadTest
     85     @Test
     86     public void testSetActionBarTitle() {
     87         final String newTitle = "hello";
     88         mActivityTestRule.getActivity().setTitle(newTitle);
     89         assertEquals("New title is set to ActionBar",
     90                 newTitle, mActivityTestRule.getActivity().getSupportActionBar().getTitle());
     91     }
     92 
     93     @Test
     94     @SdkSuppress(minSdkVersion = 16)
     95     @RequiresApi(16)
     96     public void testFitSystemWindowsReachesContent() {
     97         final FitWindowsContentLayout content =
     98                 mActivityTestRule.getActivity().findViewById(R.id.test_content);
     99         assertNotNull(content);
    100 
    101         if (!canShowSystemUi(mActivityTestRule.getActivity())) {
    102             // Device cannot show system UI so setSystemUiVisibility will do nothing.
    103             return;
    104         }
    105 
    106         // Call setSystemUiVisibility with flags which will cause window insets to be dispatched
    107         final int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    108         onView(withId(R.id.test_content)).perform(setSystemUiVisibility(flags));
    109 
    110         assertTrue(content.getFitsSystemWindowsCalled());
    111     }
    112 
    113     @Test
    114     @SdkSuppress(minSdkVersion = 21)
    115     @RequiresApi(21)
    116     public void testOnApplyWindowInsetsReachesContent() {
    117         final View content = mActivityTestRule.getActivity().findViewById(R.id.test_content);
    118         assertNotNull(content);
    119 
    120         if (!canShowSystemUi(mActivityTestRule.getActivity())) {
    121             // Device cannot show system UI so setSystemUiVisibility will do nothing.
    122             return;
    123         }
    124 
    125         // Create a spy of one of our test listener and set it on our content
    126         final View.OnApplyWindowInsetsListener spyListener
    127                 = spy(new TestOnApplyWindowInsetsListener());
    128         content.setOnApplyWindowInsetsListener(spyListener);
    129 
    130         // Call setSystemUiVisibility with flags which will cause window insets to be dispatched
    131         final int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    132         onView(withId(R.id.test_content)).perform(setSystemUiVisibility(flags));
    133 
    134         // Verify that the listener was called at least once
    135         verify(spyListener, atLeastOnce())
    136                 .onApplyWindowInsets(eq(content), any(WindowInsets.class));
    137     }
    138 
    139     @Test
    140     @UiThreadTest
    141     public void testSupportActionModeCallbacks() {
    142         final A activity = mActivityTestRule.getActivity();
    143 
    144         // Create a mock action mode callback which returns true from onCreateActionMode
    145         final ActionMode.Callback callback = mock(ActionMode.Callback.class);
    146         when(callback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).thenReturn(true);
    147 
    148         // Start an action mode
    149         final ActionMode actionMode = activity.startSupportActionMode(callback);
    150         assertNotNull(actionMode);
    151 
    152         // Now verify that onCreateActionMode and onPrepareActionMode are called once
    153         verify(callback).onCreateActionMode(any(ActionMode.class), any(Menu.class));
    154         verify(callback).onPrepareActionMode(any(ActionMode.class), any(Menu.class));
    155 
    156         // Now finish and verify that onDestroyActionMode is called once, and there are no more
    157         // interactions
    158         actionMode.finish();
    159         verify(callback).onDestroyActionMode(any(ActionMode.class));
    160         verifyNoMoreInteractions(callback);
    161     }
    162 
    163     @Test
    164     @UiThreadTest
    165     public void testSupportActionModeCallbacksInvalidate() {
    166         final A activity = mActivityTestRule.getActivity();
    167 
    168         // Create a mock action mode callback which returns true from onCreateActionMode
    169         final ActionMode.Callback callback = mock(ActionMode.Callback.class);
    170         when(callback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).thenReturn(true);
    171 
    172         // Start an action mode
    173         final ActionMode actionMode = activity.startSupportActionMode(callback);
    174         // Assert that one was created
    175         assertNotNull(actionMode);
    176         // Reset the mock so that any callback counts from the create are reset
    177         reset(callback);
    178 
    179         // Now invalidate the action mode
    180         actionMode.invalidate();
    181 
    182         // Now verify that onCreateActionMode is not called, and onPrepareActionMode is called once
    183         verify(callback, never()).onCreateActionMode(any(ActionMode.class), any(Menu.class));
    184         verify(callback).onPrepareActionMode(any(ActionMode.class), any(Menu.class));
    185     }
    186 
    187     @Test
    188     @UiThreadTest
    189     public void testSupportActionModeCallbacksWithFalseOnCreate() {
    190         final A activity = mActivityTestRule.getActivity();
    191 
    192         // Create a mock action mode callback which returns true from onCreateActionMode
    193         final ActionMode.Callback callback = mock(ActionMode.Callback.class);
    194         when(callback.onCreateActionMode(any(ActionMode.class), any(Menu.class))).thenReturn(false);
    195 
    196         // Start an action mode
    197         final ActionMode actionMode = activity.startSupportActionMode(callback);
    198 
    199         // Now verify that onCreateActionMode is called once
    200         verify(callback).onCreateActionMode(any(ActionMode.class), any(Menu.class));
    201 
    202         // Now verify that onPrepareActionMode is not called (since onCreateActionMode
    203         // returns false)
    204         verify(callback, never()).onPrepareActionMode(any(ActionMode.class), any(Menu.class));
    205 
    206         // Assert that an action mode was not created
    207         assertNull(actionMode);
    208     }
    209 
    210     @SuppressWarnings("deprecation")
    211     @SuppressLint("InlinedApi")
    212     private static boolean canShowSystemUi(Activity activity) {
    213         PackageManager manager = activity.getPackageManager();
    214         return !manager.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
    215                 && !manager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
    216                 && !manager.hasSystemFeature(PackageManager.FEATURE_WATCH);
    217     }
    218 
    219     protected void testSupportActionModeAppCompatCallbacks(final boolean fromWindow) {
    220         final A activity = mActivityTestRule.getActivity();
    221 
    222         // Create a mock action mode callback which returns true from onCreateActionMode
    223         final ActionMode.Callback amCallback = mock(ActionMode.Callback.class);
    224         when(amCallback.onCreateActionMode(any(ActionMode.class), any(Menu.class)))
    225                 .thenReturn(true);
    226 
    227         // Create a mock AppCompatCallback, which returns null from
    228         // onWindowStartingSupportActionMode, and set it on the Activity
    229         final AppCompatCallback apCallback = mock(AppCompatCallback.class);
    230         when(apCallback.onWindowStartingSupportActionMode(any(ActionMode.Callback.class)))
    231                 .thenReturn(null);
    232         activity.setAppCompatCallback(apCallback);
    233 
    234         // Start an action mode with the action mode callback
    235         final ActionMode actionMode = activity.startSupportActionMode(amCallback);
    236 
    237         if (fromWindow) {
    238             // Verify that the callback's onWindowStartingSupportActionMode was called
    239             verify(apCallback).onWindowStartingSupportActionMode(any(ActionMode.Callback.class));
    240         }
    241 
    242         // Now assert that an action mode was created
    243         assertNotNull(actionMode);
    244 
    245         // Now verify that onSupportActionModeStarted is called once
    246         verify(apCallback).onSupportActionModeStarted(any(ActionMode.class));
    247 
    248         // Now finish and verify that onDestroyActionMode is called once
    249         actionMode.finish();
    250         verify(apCallback).onSupportActionModeFinished(any(ActionMode.class));
    251     }
    252 
    253     public static class TestOnApplyWindowInsetsListener
    254             implements View.OnApplyWindowInsetsListener {
    255         @Override
    256         public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
    257             return windowInsets;
    258         }
    259     }
    260 }
    261