Loading tests/common/com/android/documentsui/conditions/HasChildCountCondition.kt 0 → 100644 +46 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.documentsui.conditions import androidx.test.uiautomator.UiObject2 import androidx.test.uiautomator.UiObject2Condition /** * A UI Automator condition that is met when the UiObject2 that it is acting on has the number of * children elements that matches the supplied `predicate`. The companion object contains some * shorthand helpers for common cases. The object that it is checking the child count of must exist. */ class HasChildCountCondition( private val predicate: (count: Int) -> Boolean ) : UiObject2Condition<Boolean>() { override fun apply(o: UiObject2?): Boolean? { requireNotNull(o) { "Supplied object to validate for child count must exist" } return predicate(o.childCount) } companion object { @JvmStatic fun hasOneChild(): HasChildCountCondition { return HasChildCountCondition({ it == 1 }) } @JvmStatic fun hasMoreThanOneChild(): HasChildCountCondition { return HasChildCountCondition({ it > 1 }) } } } tests/functional/com/android/documentsui/SearchViewUiTest.java +35 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.android.documentsui.StubProvider.ROOT_0_ID; import static com.android.documentsui.StubProvider.ROOT_1_ID; import static com.android.documentsui.conditions.HasChildCountCondition.hasMoreThanOneChild; import static com.android.documentsui.conditions.HasChildCountCondition.hasOneChild; import static com.android.documentsui.flags.Flags.FLAG_USE_MATERIAL3; import static com.android.documentsui.flags.Flags.FLAG_USE_SEARCH_V2_READ_ONLY; Loading @@ -41,6 +43,7 @@ import android.provider.Settings; import androidx.test.filters.LargeTest; import androidx.test.filters.Suppress; import androidx.test.uiautomator.By; import androidx.test.uiautomator.UiObject2; import androidx.test.uiautomator.UiObjectNotFoundException; import androidx.test.uiautomator.Until; Loading @@ -63,6 +66,9 @@ public class SearchViewUiTest extends ActivityTestJunit4<FilesActivity> { @Rule public final TestFilesRule mTestFilesRule = new TestFilesRule(); // UI timeout to wait for elements to appear, set to 5 seconds. private final int mTimeout = 5000; @Before public void setUpTest() throws UiObjectNotFoundException, RemoteException { // Drawer interferes with a lot of search action; going to try to close any opened ones Loading Loading @@ -354,7 +360,35 @@ public class SearchViewUiTest extends ActivityTestJunit4<FilesActivity> { .perform(new RelaxedClickAction()); // Ensure the selection has cleared and the "1 file selected" text is not displayed. device.wait(Until.findObject(By.text(TestFilesRule.FILE_NAME_2).selected(false)), 5000); device.wait(Until.findObject(By.text(TestFilesRule.FILE_NAME_2).selected(false)), mTimeout); onView(withText("1 selected")).check(doesNotExist()); } @Test @RequiresFlagsDisabled( FLAG_USE_MATERIAL3) // TODO(b/412895530): Enable for `use_material3` once fixed. public void testSelectionWhileSearchingHidesSearchBar() throws UiObjectNotFoundException { String pkg = bots.directory.mTargetPackage; // The `mTestFilesRule` creates more than 1 file, so ensure that that is the case before // proceeding. UiObject2 directoryList = device.findObject(By.res(pkg + ":id/dir_list")); directoryList.wait(hasMoreThanOneChild(), mTimeout); // Click the search icon and wait until the only result is the file that was searced for. bots.search.clickIcon(); bots.search.setInputText(TestFilesRule.FILE_NAME_1); directoryList.wait(hasOneChild(), mTimeout); bots.directory.waitForDocument(TestFilesRule.FILE_NAME_1); // Select the document. This implicitly verifies that the bar at the top shows the text "1 // selected" which, in all conditions, occludes the search input box. bots.directory.selectDocument(TestFilesRule.FILE_NAME_1, 1); // Deselect the document and click the clear button on the search view (if the selection bar // at the top is visible this won't be possible). bots.directory.selectDocument(TestFilesRule.FILE_NAME_1); bots.search.clickSearchViewClearButton(); device.wait(Until.findObject(By.res(pkg + ":id/history_list")), mTimeout); } } Loading
tests/common/com/android/documentsui/conditions/HasChildCountCondition.kt 0 → 100644 +46 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.documentsui.conditions import androidx.test.uiautomator.UiObject2 import androidx.test.uiautomator.UiObject2Condition /** * A UI Automator condition that is met when the UiObject2 that it is acting on has the number of * children elements that matches the supplied `predicate`. The companion object contains some * shorthand helpers for common cases. The object that it is checking the child count of must exist. */ class HasChildCountCondition( private val predicate: (count: Int) -> Boolean ) : UiObject2Condition<Boolean>() { override fun apply(o: UiObject2?): Boolean? { requireNotNull(o) { "Supplied object to validate for child count must exist" } return predicate(o.childCount) } companion object { @JvmStatic fun hasOneChild(): HasChildCountCondition { return HasChildCountCondition({ it == 1 }) } @JvmStatic fun hasMoreThanOneChild(): HasChildCountCondition { return HasChildCountCondition({ it > 1 }) } } }
tests/functional/com/android/documentsui/SearchViewUiTest.java +35 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.android.documentsui.StubProvider.ROOT_0_ID; import static com.android.documentsui.StubProvider.ROOT_1_ID; import static com.android.documentsui.conditions.HasChildCountCondition.hasMoreThanOneChild; import static com.android.documentsui.conditions.HasChildCountCondition.hasOneChild; import static com.android.documentsui.flags.Flags.FLAG_USE_MATERIAL3; import static com.android.documentsui.flags.Flags.FLAG_USE_SEARCH_V2_READ_ONLY; Loading @@ -41,6 +43,7 @@ import android.provider.Settings; import androidx.test.filters.LargeTest; import androidx.test.filters.Suppress; import androidx.test.uiautomator.By; import androidx.test.uiautomator.UiObject2; import androidx.test.uiautomator.UiObjectNotFoundException; import androidx.test.uiautomator.Until; Loading @@ -63,6 +66,9 @@ public class SearchViewUiTest extends ActivityTestJunit4<FilesActivity> { @Rule public final TestFilesRule mTestFilesRule = new TestFilesRule(); // UI timeout to wait for elements to appear, set to 5 seconds. private final int mTimeout = 5000; @Before public void setUpTest() throws UiObjectNotFoundException, RemoteException { // Drawer interferes with a lot of search action; going to try to close any opened ones Loading Loading @@ -354,7 +360,35 @@ public class SearchViewUiTest extends ActivityTestJunit4<FilesActivity> { .perform(new RelaxedClickAction()); // Ensure the selection has cleared and the "1 file selected" text is not displayed. device.wait(Until.findObject(By.text(TestFilesRule.FILE_NAME_2).selected(false)), 5000); device.wait(Until.findObject(By.text(TestFilesRule.FILE_NAME_2).selected(false)), mTimeout); onView(withText("1 selected")).check(doesNotExist()); } @Test @RequiresFlagsDisabled( FLAG_USE_MATERIAL3) // TODO(b/412895530): Enable for `use_material3` once fixed. public void testSelectionWhileSearchingHidesSearchBar() throws UiObjectNotFoundException { String pkg = bots.directory.mTargetPackage; // The `mTestFilesRule` creates more than 1 file, so ensure that that is the case before // proceeding. UiObject2 directoryList = device.findObject(By.res(pkg + ":id/dir_list")); directoryList.wait(hasMoreThanOneChild(), mTimeout); // Click the search icon and wait until the only result is the file that was searced for. bots.search.clickIcon(); bots.search.setInputText(TestFilesRule.FILE_NAME_1); directoryList.wait(hasOneChild(), mTimeout); bots.directory.waitForDocument(TestFilesRule.FILE_NAME_1); // Select the document. This implicitly verifies that the bar at the top shows the text "1 // selected" which, in all conditions, occludes the search input box. bots.directory.selectDocument(TestFilesRule.FILE_NAME_1, 1); // Deselect the document and click the clear button on the search view (if the selection bar // at the top is visible this won't be possible). bots.directory.selectDocument(TestFilesRule.FILE_NAME_1); bots.search.clickSearchViewClearButton(); device.wait(Until.findObject(By.res(pkg + ":id/history_list")), mTimeout); } }