Merge "Add tests for TV Pip notification intents"

This commit is contained in:
TreeHugger Robot
2020-11-05 10:25:27 +00:00
committed by Android (Google) Code Review
5 changed files with 96 additions and 9 deletions

View File

@@ -74,13 +74,17 @@ class NotificationListener : NotificationListenerService() {
return wait { instance == null }
}
fun waitForNotificationToAppear(predicate: (StatusBarNotification) -> Boolean): Boolean {
fun waitForNotificationToAppear(
predicate: (StatusBarNotification) -> Boolean
): StatusBarNotification? {
return instance?.let {
wait { it.notifications.values.any(predicate) }
waitForResult(extractor = { it.notifications.values.first(predicate) }).second
} ?: throw IllegalStateException("NotificationListenerService is not connected")
}
fun waitForNotificationToDisappear(predicate: (StatusBarNotification) -> Boolean): Boolean {
fun waitForNotificationToDisappear(
predicate: (StatusBarNotification) -> Boolean
): Boolean {
return instance?.let {
wait { it.notifications.values.none(predicate) }
} ?: throw IllegalStateException("NotificationListenerService is not connected")

View File

@@ -66,6 +66,10 @@ abstract class BaseAppHelper(
uiDevice.wait(Until.hasObject(appSelector), APP_LAUNCH_WAIT_TIME_MS)
}
fun waitUntilClosed(): Boolean {
return uiDevice.wait(Until.gone(appSelector), APP_CLOSE_WAIT_TIME_MS)
}
fun forceStop() = activityManager?.forceStopPackage(packageName)
override fun getOpenAppIntent(): Intent {
@@ -77,5 +81,6 @@ abstract class BaseAppHelper(
companion object {
private const val APP_LAUNCH_WAIT_TIME_MS = 10_000L
private const val APP_CLOSE_WAIT_TIME_MS = 3_000L
}
}

View File

@@ -65,8 +65,7 @@ class PipAppHelper(
assertNotNull("Pip menu close button is not found", closeButton)
closeButton.click()
// Give it 1 second, just in case
SystemClock.sleep(1_000)
waitUntilClosed()
}
}
}

View File

@@ -17,6 +17,8 @@
package com.android.wm.shell.flicker.pip.tv
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
@@ -25,6 +27,7 @@ import com.android.wm.shell.flicker.NotificationListener.Companion.stopNotificat
import com.android.wm.shell.flicker.NotificationListener.Companion.waitForNotificationToAppear
import com.android.wm.shell.flicker.NotificationListener.Companion.waitForNotificationToDisappear
import org.junit.After
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.FixMethodOrder
@@ -64,7 +67,7 @@ class TvPipNotificationTests(rotationName: String, rotation: Int)
testApp.launchViaIntent()
testApp.clickEnterPipButton()
assertTrue("Pip notification should have been posted",
assertNotNull("Pip notification should have been posted",
waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.label) })
testApp.closePipWindow()
@@ -73,6 +76,43 @@ class TvPipNotificationTests(rotationName: String, rotation: Int)
waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.label) })
}
@Test
fun pipNotification_closeIntent() {
testApp.launchViaIntent()
testApp.clickEnterPipButton()
val notification: StatusBarNotification = waitForNotificationToAppear {
it.isPipNotificationWithTitle(testApp.label)
} ?: throw AssertionError("Pip notification should have been posted")
notification.deleteIntent?.send()
?: throw AssertionError("Pip notification should contain `delete_intent`")
assertTrue("Pip should have closed by sending the `delete_intent`",
testApp.waitUntilClosed())
assertTrue("Pip notification should have been dismissed",
waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.label) })
}
@Test
fun pipNotification_menuIntent() {
testApp.launchViaIntent()
testApp.clickEnterPipButton()
val notification: StatusBarNotification = waitForNotificationToAppear {
it.isPipNotificationWithTitle(testApp.label)
} ?: throw AssertionError("Pip notification should have been posted")
notification.contentIntent?.send()
?: throw AssertionError("Pip notification should contain `content_intent`")
assertTrue("Pip menu should have been shown after sending `content_intent`",
uiDevice.waitForTvPipMenu())
uiDevice.pressBack()
testApp.closePipWindow()
}
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
@@ -83,10 +123,23 @@ class TvPipNotificationTests(rotationName: String, rotation: Int)
}
}
private const val PIP_NOTIFICATION_TAG = "PipNotification"
private val StatusBarNotification.extras: Bundle?
get() = notification?.extras
private val StatusBarNotification.title: String
get() = notification?.extras?.getString(Notification.EXTRA_TITLE) ?: ""
get() = extras?.getString(Notification.EXTRA_TITLE) ?: ""
/** Get TV extensions with [android.app.Notification.TvExtender.EXTRA_TV_EXTENDER]. */
private val StatusBarNotification.tvExtensions: Bundle?
get() = extras?.getBundle("android.tv.EXTENSIONS")
/** "Content" TV intent with key [android.app.Notification.TvExtender.EXTRA_CONTENT_INTENT]. */
private val StatusBarNotification.contentIntent: PendingIntent?
get() = tvExtensions?.getParcelable("content_intent")
/** "Delete" TV intent with key [android.app.Notification.TvExtender.EXTRA_DELETE_INTENT]. */
private val StatusBarNotification.deleteIntent: PendingIntent?
get() = tvExtensions?.getParcelable("delete_intent")
private fun StatusBarNotification.isPipNotificationWithTitle(expectedTitle: String): Boolean =
tag == PIP_NOTIFICATION_TAG && title == expectedTitle
tag == "PipNotification" && title == expectedTitle

View File

@@ -0,0 +1,26 @@
/*
* 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 androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
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
}