• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.android.permissioncontroller.permission.ui.television
18 
19 import androidx.test.uiautomator.By
20 import androidx.test.uiautomator.StaleObjectException
21 import androidx.test.uiautomator.UiDevice
22 import androidx.test.uiautomator.UiObject2
23 import androidx.test.uiautomator.Until
24 
25 private val SELECTOR_FOCUSED = By.focused(true)
26 private val SELECTOR_RES_ID_PC_DECOR_TITLE =
27     By.res("com.android.permissioncontroller", "decor_title")
28 private val SELECTOR_RES_ID_ANDROID_TITLE = By.res("android", "title")
29 
30 private const val WAIT_DELAY = 3_000L
31 private const val RETRIES = 5
32 
33 val UiDevice.fragmentDecorTitle: String?
34     get() = wait(Until.findObject(SELECTOR_RES_ID_PC_DECOR_TITLE), WAIT_DELAY)?.text
35 
36 val UiDevice.focusedElement: UiObject2
37     get() = wait(Until.findObject(SELECTOR_FOCUSED), WAIT_DELAY)
38         ?: error("Focused item is not found")
39 
40 private val UiObject2.titleElement: UiObject2
41     get() = wait(Until.findObject(SELECTOR_RES_ID_ANDROID_TITLE), WAIT_DELAY)
42         ?: error("Could not retrieve title")
43 
44 val UiDevice.focusedElementTitle: String?
45     get() {
<lambda>null46         repeat(RETRIES) {
47             try { return focusedElement.titleElement.text } catch (e: StaleObjectException) {}
48         }
49         error("Could not get title text")
50     }
51 
<lambda>null52 fun UiDevice.navigateDown() = navigate { pressDPadDown() }
53 
<lambda>null54 fun UiDevice.navigateUp() = navigate { pressDPadUp() }
55 
56 @Suppress("ControlFlowWithEmptyBody")
UiDevicenull57 fun UiDevice.navigateToTheBottom() {
58     while (navigateDown()) {}
59 }
60 
61 @Suppress("ControlFlowWithEmptyBody")
navigateToTheTopnull62 fun UiDevice.navigateToTheTop() {
63     while (navigateUp()) {}
64 }
65 
UiDevicenull66 fun UiDevice.focusOnElementWithTitle(title: CharSequence): Boolean =
67     checkAllItemsIfNeeded { focusedElementTitle == title }
68 
hasElementWithTitlenull69 fun UiDevice.hasElementWithTitle(title: CharSequence): Boolean =
70     checkAllItemsIfNeeded {
71         hasObject(By.copy(SELECTOR_RES_ID_ANDROID_TITLE).text(title.toString()))
72     }
73 
UiDevicenull74 private fun UiDevice.checkAllItemsIfNeeded(predicate: () -> Boolean): Boolean {
75     // Let's do one quick check first, right where we are. If it does not work - we'll do the walk.
76     if (predicate()) return true
77 
78     // That didn't work, so we'll go over all the items in the list (if needed) top to bottom, but
79     // let's make sure we start from the very top.
80     navigateToTheTop()
81 
82     do {
83         if (predicate()) return true
84     } while (navigateDown())
85 
86     return false
87 }
88 
navigatenull89 private fun UiDevice.navigate(action: () -> Unit): Boolean {
90     val prevFocusedTitle = focusedElementTitle
91 
92     action()
93     waitForIdle()
94 
95     return prevFocusedTitle != focusedElementTitle
96 }