Home | History | Annotate | Download | only in pictureinpicture
      1 /*
      2  * Copyright (C) 2017 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.example.android.pictureinpicture;
     18 
     19 import static android.support.test.espresso.Espresso.onView;
     20 import static android.support.test.espresso.action.ViewActions.click;
     21 import static android.support.test.espresso.assertion.ViewAssertions.matches;
     22 import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
     23 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
     24 import static android.support.test.espresso.matcher.ViewMatchers.withId;
     25 
     26 import static org.hamcrest.Matchers.not;
     27 import static org.hamcrest.core.AllOf.allOf;
     28 import static org.junit.Assert.assertNotNull;
     29 import static org.junit.Assert.assertThat;
     30 import static org.junit.Assert.assertTrue;
     31 
     32 import android.content.pm.ActivityInfo;
     33 import android.support.test.InstrumentationRegistry;
     34 import android.support.test.espresso.UiController;
     35 import android.support.test.espresso.ViewAction;
     36 import android.support.test.rule.ActivityTestRule;
     37 import android.support.test.runner.AndroidJUnit4;
     38 import android.view.View;
     39 
     40 import com.example.android.pictureinpicture.widget.MovieView;
     41 
     42 import org.hamcrest.Description;
     43 import org.hamcrest.Matcher;
     44 import org.hamcrest.TypeSafeMatcher;
     45 import org.junit.Rule;
     46 import org.junit.Test;
     47 import org.junit.runner.RunWith;
     48 
     49 
     50 @RunWith(AndroidJUnit4.class)
     51 public class MainActivityTest {
     52 
     53     @Rule
     54     public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class);
     55 
     56     @Test
     57     public void movie_playingOnPip() throws Throwable {
     58         // The movie should be playing on start
     59         onView(withId(R.id.movie))
     60                 .check(matches(allOf(isDisplayed(), isPlaying())))
     61                 .perform(showControls());
     62         // Click on the button to enter Picture-in-Picture mode
     63         onView(withId(R.id.minimize)).perform(click());
     64         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     65         // The Activity is paused. We cannot use Espresso to test paused activities.
     66         rule.runOnUiThread(new Runnable() {
     67             @Override
     68             public void run() {
     69                 // We are now in Picture-in-Picture mode
     70                 assertTrue(rule.getActivity().isInPictureInPictureMode());
     71                 final MovieView view = rule.getActivity().findViewById(R.id.movie);
     72                 assertNotNull(view);
     73                 // The video should still be playing
     74                 assertTrue(view.isPlaying());
     75             }
     76         });
     77     }
     78 
     79     @Test
     80     public void movie_pauseAndResume() throws Throwable {
     81         // The movie should be playing on start
     82         onView(withId(R.id.movie))
     83                 .check(matches(allOf(isDisplayed(), isPlaying())))
     84                 .perform(showControls());
     85         // Pause
     86         onView(withId(R.id.toggle)).perform(click());
     87         onView(withId(R.id.movie)).check(matches((not(isPlaying()))));
     88         // Resume
     89         onView(withId(R.id.toggle)).perform(click());
     90         onView(withId(R.id.movie)).check(matches(isPlaying()));
     91     }
     92 
     93     @Test
     94     public void fullscreen_enabledOnLandscape() throws Throwable {
     95         rule.runOnUiThread(new Runnable() {
     96             @Override
     97             public void run() {
     98                 rule.getActivity()
     99                         .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    100             }
    101         });
    102         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    103         rule.runOnUiThread(new Runnable() {
    104             @Override
    105             public void run() {
    106                 final View decorView = rule.getActivity().getWindow().getDecorView();
    107                 assertThat(decorView.getSystemUiVisibility(),
    108                         hasFlag(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN));
    109             }
    110         });
    111     }
    112 
    113     @Test
    114     public void fullscreen_disabledOnPortrait() throws Throwable {
    115         rule.runOnUiThread(new Runnable() {
    116             @Override
    117             public void run() {
    118                 rule.getActivity()
    119                         .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    120             }
    121         });
    122         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    123         rule.runOnUiThread(new Runnable() {
    124             @Override
    125             public void run() {
    126                 final View decorView = rule.getActivity().getWindow().getDecorView();
    127                 assertThat(decorView.getSystemUiVisibility(),
    128                         not(hasFlag(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)));
    129             }
    130         });
    131     }
    132 
    133     private static Matcher<? super View> isPlaying() {
    134         return new TypeSafeMatcher<View>() {
    135             @Override
    136             protected boolean matchesSafely(View view) {
    137                 return ((MovieView) view).isPlaying();
    138             }
    139 
    140             @Override
    141             public void describeTo(Description description) {
    142                 description.appendText("MovieView is playing");
    143             }
    144         };
    145     }
    146 
    147     private static ViewAction showControls() {
    148         return new ViewAction() {
    149             @Override
    150             public Matcher<View> getConstraints() {
    151                 return isAssignableFrom(MovieView.class);
    152             }
    153 
    154             @Override
    155             public String getDescription() {
    156                 return "Show controls of MovieView";
    157             }
    158 
    159             @Override
    160             public void perform(UiController uiController, View view) {
    161                 uiController.loopMainThreadUntilIdle();
    162                 ((MovieView) view).showControls();
    163                 uiController.loopMainThreadUntilIdle();
    164             }
    165         };
    166     }
    167 
    168     private static Matcher<? super Integer> hasFlag(final int flag) {
    169         return new TypeSafeMatcher<Integer>() {
    170             @Override
    171             protected boolean matchesSafely(Integer i) {
    172                 return (i & flag) == flag;
    173             }
    174 
    175             @Override
    176             public void describeTo(Description description) {
    177                 description.appendText("Flag integer contains " + flag);
    178             }
    179         };
    180     }
    181 
    182 }
    183