Add TvPipMenuTests

Bug: 171520419
Test: atest WMShellFlickerTests:TvPipMenuTests
Change-Id: If74cb25f6c1c46704f35d2c8073c0fdb50c8d7eb
This commit is contained in:
Sergey Nikolaienkov
2020-11-06 07:35:47 +00:00
parent fbc3469d7b
commit 50118593eb
6 changed files with 156 additions and 14 deletions

View File

@@ -15,6 +15,7 @@
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv_pip_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"

View File

@@ -26,6 +26,7 @@ import android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY
import android.support.test.launcherhelper.LauncherStrategyFactory
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.wm.shell.flicker.TEST_APP_PACKAGE_NAME
@@ -60,6 +61,9 @@ abstract class BaseAppHelper(
getApplicationLabel(getApplicationInfo(packageName, 0)).toString()
}
val ui: UiObject2?
get() = uiDevice.findObject(appSelector)
fun launchViaIntent() {
context.startActivity(openAppIntent)

View File

@@ -0,0 +1,112 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wm.shell.flicker.pip.tv
import android.os.SystemClock
import androidx.test.filters.RequiresDevice
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
/**
* Test Pip Menu on TV.
* To run this test: `atest WMShellFlickerTests:TvPipMenuTests`
*/
@RequiresDevice
@RunWith(Parameterized::class)
class TvPipMenuTests(rotationName: String, rotation: Int)
: TvPipTestBase(rotationName, rotation) {
@Before
override fun setUp() {
super.setUp()
// Launch the app and go to PiP
testApp.launchViaIntent()
testApp.clickEnterPipButton()
}
@Test
fun pipMenu_open() {
// Pressing the Window key should bring up Pip menu
uiDevice.pressWindowKey()
val pipMenu = uiDevice.waitForTvPipMenu()
?: fail("Pip notification should have been dismissed")
assertTrue("Pip menu should be shown fullscreen", pipMenu.isFullscreen(uiDevice))
testApp.closePipWindow()
}
@Test
fun pipMenu_backButton() {
// Pressing the Window key should bring up Pip menu
uiDevice.pressWindowKey()
assertNotNull("Pip notification should have been dismissed", uiDevice.waitForTvPipMenu())
// Pressing the Back key should close the Pip menu
uiDevice.pressBack()
assertTrue("Pip notification should have closed", uiDevice.waitForTvPipMenuToClose())
testApp.closePipWindow()
}
@Test
fun pipMenu_closeButton() {
// Pressing the Window key should bring up Pip menu
uiDevice.pressWindowKey()
assertNotNull("Pip notification should have been dismissed", uiDevice.waitForTvPipMenu())
// PiP menu should contain the Close button
val closeButton = uiDevice.findTvPipMenuCloseButton()
?: fail("\"Close PIP\" button should be shown in Pip menu")
// Clicking on the Close button should close the app
closeButton.click()
assertTrue("\"Close PIP\" button should close the PiP", testApp.waitUntilClosed())
}
@Test
fun pipMenu_fullscreenButton() {
// Pressing the Window key should bring up Pip menu
uiDevice.pressWindowKey()
assertNotNull("Pip notification should have been dismissed", uiDevice.waitForTvPipMenu())
// PiP menu should contain the Fullscreen button
val fullscreenButton = uiDevice.findTvPipMenuFullscreenButton()
?: fail("\"Full screen\" button should be shown in Pip menu")
// Clicking on the fullscreen button should return app to the fullscreen mode.
// Click, wait for 3 seconds, check the app is fullscreen
fullscreenButton.click()
SystemClock.sleep(3_000L)
assertTrue("\"Full screen\" button should open the app fullscreen",
testApp.ui?.isFullscreen(uiDevice) ?: false)
// Close the app
uiDevice.pressBack()
testApp.waitUntilClosed()
}
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<Array<Any>> = rotationParams
}
}

View File

@@ -20,7 +20,6 @@ import android.app.Notification
import android.app.PendingIntent
import android.os.Bundle
import android.service.notification.StatusBarNotification
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.wm.shell.flicker.NotificationListener.Companion.findNotification
import com.android.wm.shell.flicker.NotificationListener.Companion.startNotificationListener
@@ -32,10 +31,8 @@ import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
@@ -44,7 +41,6 @@ import org.junit.runners.Parameterized
*/
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TvPipNotificationTests(rotationName: String, rotation: Int)
: TvPipTestBase(rotationName, rotation) {
@@ -60,7 +56,6 @@ class TvPipNotificationTests(rotationName: String, rotation: Int)
@After
override fun tearDown() {
stopNotificationListener()
testApp.forceStop()
super.tearDown()
}
@@ -108,7 +103,7 @@ class TvPipNotificationTests(rotationName: String, rotation: Int)
notification.contentIntent?.send()
?: fail("Pip notification should contain `content_intent`")
assertTrue("Pip menu should have been shown after sending `content_intent`",
assertNotNull("Pip menu should have been shown after sending `content_intent`",
uiDevice.waitForTvPipMenu())
uiDevice.pressBack()
@@ -156,18 +151,13 @@ class TvPipNotificationTests(rotationName: String, rotation: Int)
testApp.closePipWindow()
}
private fun fail(message: String): Nothing = throw AssertionError(message)
companion object {
private const val TITLE_MEDIA_SESSION_PLAYING = "TestApp media is playing"
private const val TITLE_MEDIA_SESSION_PAUSED = "TestApp media is paused"
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<Array<Any>> {
val supportedRotations = intArrayOf(Surface.ROTATION_0)
return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
}
fun getParams(): Collection<Array<Any>> = rotationParams
}
}

View File

@@ -18,6 +18,8 @@ package com.android.wm.shell.flicker.pip.tv
import android.content.pm.PackageManager.FEATURE_LEANBACK
import android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY
import android.view.Surface.ROTATION_0
import android.view.Surface.rotationToString
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.wm.shell.flicker.pip.PipTestBase
import org.junit.After
@@ -40,5 +42,14 @@ abstract class TvPipTestBase(rotationName: String, rotation: Int)
@After
open fun tearDown() {
testApp.forceStop()
}
protected fun fail(message: String): Nothing = throw AssertionError(message)
companion object {
@JvmStatic
protected val rotationParams: Collection<Array<Any>> =
listOf(arrayOf(rotationToString(ROTATION_0), ROTATION_0))
}
}

View File

@@ -16,11 +16,35 @@
package com.android.wm.shell.flicker.pip.tv
import android.view.KeyEvent
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
fun UiDevice.waitForTvPipMenu(): Boolean {
return wait(Until.findObject(By.res(SYSTEM_UI_PACKAGE_NAME, "pip_controls")), 3_000) != null
/** Id of the root view in the com.android.wm.shell.pip.tv.PipMenuActivity */
private const val TV_PIP_MENU_ROOT_ID = "tv_pip_menu"
private const val TV_PIP_MENU_CLOSE_BUTTON_ID = "close_button"
private const val TV_PIP_MENU_FULLSCREEN_BUTTON_ID = "full_button"
private const val WAIT_TIME_MS = 3_000L
private val tvPipMenuSelector = By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_ROOT_ID)
fun UiDevice.pressWindowKey() = pressKeyCode(KeyEvent.KEYCODE_WINDOW)
fun UiDevice.waitForTvPipMenu(): UiObject2? =
wait(Until.findObject(tvPipMenuSelector), WAIT_TIME_MS)
fun UiDevice.waitForTvPipMenuToClose(): Boolean = wait(Until.gone(tvPipMenuSelector), WAIT_TIME_MS)
fun UiDevice.findTvPipMenuCloseButton(): UiObject2? = findObject(
By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_CLOSE_BUTTON_ID))
fun UiDevice.findTvPipMenuFullscreenButton(): UiObject2? = findObject(
By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_FULLSCREEN_BUTTON_ID))
fun UiObject2.isFullscreen(uiDevice: UiDevice): Boolean = visibleBounds.run {
height() == uiDevice.displayHeight && width() == uiDevice.displayWidth
}