diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java index a34dd55032e65..845e32cebd0f0 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java @@ -317,6 +317,12 @@ public abstract class BaseActivity extends Activity CreateDirectoryFragment.show(getFragmentManager()); } + void onDirectoryCreated(DocumentInfo doc) { + // By default we do nothing, just let the new directory appear. + // DocumentsActivity auto-opens directories after creating them + // As that is more attuned to the "picker" use cases it supports. + } + /** * Returns true if a directory can be created in the current location. * @return @@ -331,11 +337,6 @@ public abstract class BaseActivity extends Activity && !root.isDownloads(); } - void onDirectoryCreated(DocumentInfo doc) { - checkArgument(doc.isDirectory()); - openContainerDocument(doc); - } - void openContainerDocument(DocumentInfo doc) { checkArgument(doc.isContainer()); mState.pushDocument(doc); diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index 9812495da0fd9..6ecdc905a60be 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -23,6 +23,7 @@ import static com.android.documentsui.State.ACTION_OPEN; import static com.android.documentsui.State.ACTION_OPEN_TREE; import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION; import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE; +import static com.android.internal.util.Preconditions.checkArgument; import android.app.Activity; import android.app.Fragment; @@ -316,6 +317,12 @@ public class DocumentsActivity extends BaseActivity { .executeOnExecutor(getExecutorForCurrentDirectory()); } + @Override + void onDirectoryCreated(DocumentInfo doc) { + checkArgument(doc.isDirectory()); + openContainerDocument(doc); + } + void onSaveRequested(String mimeType, String displayName) { new CreateFinishTask(this, mimeType, displayName) .executeOnExecutor(getExecutorForCurrentDirectory()); diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java index b8b50e47483f9..8b42ac5811b5a 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java @@ -33,7 +33,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.Parcelable; import android.provider.DocumentsContract; -import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.util.Log; import android.view.KeyEvent; diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java index 34f11207b0067..08d366a1384fd 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java @@ -21,21 +21,22 @@ import static com.android.documentsui.StubProvider.ROOT_0_ID; import static com.android.documentsui.StubProvider.ROOT_1_ID; import android.app.Activity; -import android.app.Instrumentation; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.os.RemoteException; import android.provider.DocumentsContract.Document; -import android.support.test.uiautomator.By; import android.support.test.uiautomator.Configurator; import android.support.test.uiautomator.UiDevice; import android.support.test.uiautomator.UiObjectNotFoundException; -import android.support.test.uiautomator.Until; import android.test.ActivityInstrumentationTestCase2; import android.view.MotionEvent; +import com.android.documentsui.bots.DirectoryListBot; +import com.android.documentsui.bots.KeyboardBot; +import com.android.documentsui.bots.RootsListBot; +import com.android.documentsui.bots.UiBot; import com.android.documentsui.model.RootInfo; /** @@ -56,7 +57,7 @@ public abstract class ActivityTest extends ActivityInstrumen public static final String fileName4 = "poodles.text"; public static final String fileNameNoRename = "NO_RENAMEfile.txt"; - public UiBot bot; + public Bots bots; public UiDevice device; public Context context; @@ -76,10 +77,11 @@ public abstract class ActivityTest extends ActivityInstrumen device = UiDevice.getInstance(getInstrumentation()); // NOTE: Must be the "target" context, else security checks in content provider will fail. context = getInstrumentation().getTargetContext(); - bot = new UiBot(device, context, TIMEOUT); + + bots = new Bots(device, context, TIMEOUT); Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE); - bot.revealLauncher(); + bots.main.revealLauncher(); mResolver = context.getContentResolver(); mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY); @@ -90,7 +92,7 @@ public abstract class ActivityTest extends ActivityInstrumen launchActivity(); - bot.revealApp(); + bots.main.revealApp(); resetStorage(); } @@ -125,12 +127,31 @@ public abstract class ActivityTest extends ActivityInstrumen } void assertDefaultContentOfTestDir0() throws UiObjectNotFoundException { - bot.assertDocumentsCount(ROOT_0_ID, 4); - bot.assertHasDocuments(fileName1, fileName2, dirName1, fileNameNoRename); + bots.roots.openRoot(ROOT_0_ID); + bots.directory.assertDocumentsCount(4); + bots.directory.assertDocumentsPresent(fileName1, fileName2, dirName1, fileNameNoRename); } void assertDefaultContentOfTestDir1() throws UiObjectNotFoundException { - bot.assertDocumentsCount(ROOT_1_ID, 2); - bot.assertHasDocuments(fileName3, fileName4); + bots.roots.openRoot(ROOT_1_ID); + bots.directory.assertDocumentsCount(2); + bots.directory.assertDocumentsPresent(fileName3, fileName4); + } + + /** + * Handy collection of bots for working with Files app. + */ + public static final class Bots { + public final UiBot main; + public final RootsListBot roots; + public final DirectoryListBot directory; + public final KeyboardBot keyboard; + + private Bots(UiDevice device, Context context, int timeout) { + this.main = new UiBot(device, context, TIMEOUT); + this.roots = new RootsListBot(device, context, TIMEOUT); + this.directory = new DirectoryListBot(device, context, TIMEOUT); + this.keyboard = new KeyboardBot(device, context, TIMEOUT); + } } } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java index c51f927560122..79d7887198b59 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java @@ -52,13 +52,13 @@ public class DownloadsActivityUiTest extends ActivityTest { public void testWindowTitle() throws Exception { initTestFiles(); - bot.assertWindowTitle(ROOT_0_ID); + bots.main.assertWindowTitle(ROOT_0_ID); } public void testFilesListed() throws Exception { initTestFiles(); - bot.assertHasDocuments("file0.log", "file1.png", "file2.csv"); + bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv"); } public void testFilesList_LiveUpdate() throws Exception { @@ -66,30 +66,31 @@ public class DownloadsActivityUiTest extends ActivityTest { mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich"); - bot.waitForDocument("Ham & Cheese.sandwich"); - bot.assertHasDocuments("file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich"); + bots.directory.waitForDocument("Ham & Cheese.sandwich"); + bots.directory.assertDocumentsPresent( + "file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich"); } public void testDeleteDocument() throws Exception { initTestFiles(); - bot.clickDocument("file1.png"); + bots.directory.clickDocument("file1.png"); device.waitForIdle(); - bot.menuDelete().click(); + bots.main.menuDelete().click(); - bot.waitForDeleteSnackbar(); - assertFalse(bot.hasDocuments("file1.png")); + bots.directory.waitForDeleteSnackbar(); + bots.directory.assertDocumentsAbsent("file1.png"); - bot.waitForDeleteSnackbarGone(); - assertFalse(bot.hasDocuments("file1.png")); + bots.directory.waitForDeleteSnackbarGone(); + bots.directory.assertDocumentsAbsent("file1.png"); } public void testSupportsShare() throws Exception { initTestFiles(); - bot.clickDocument("file1.png"); + bots.directory.clickDocument("file1.png"); device.waitForIdle(); - assertNotNull(bot.menuShare()); + assertNotNull(bots.main.menuShare()); } public void testClosesOnBack() throws Exception { diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java index 95515dbd6d75b..34ea96ebc9e5d 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java @@ -43,11 +43,11 @@ public class FilesActivityUiTest extends ActivityTest { public void testRootsListed() throws Exception { initTestFiles(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); // Should also have Drive, but that requires pre-configuration of devices // We omit for now. - bot.assertHasRoots( + bots.roots.assertHasRoots( "Images", "Videos", "Audio", @@ -60,93 +60,106 @@ public class FilesActivityUiTest extends ActivityTest { public void testFilesListed() throws Exception { initTestFiles(); - bot.openRoot(ROOT_0_ID); - bot.assertHasDocuments("file0.log", "file1.png", "file2.csv"); + bots.roots.openRoot(ROOT_0_ID); + bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv"); } public void testLoadsHomeDirectoryByDefault() throws Exception { initTestFiles(); device.waitForIdle(); - bot.assertWindowTitle("Documents"); + bots.main.assertWindowTitle("Documents"); } public void testRootClickSetsWindowTitle() throws Exception { initTestFiles(); - bot.openRoot("Downloads"); - bot.assertWindowTitle("Downloads"); + bots.roots.openRoot("Downloads"); + bots.main.assertWindowTitle("Downloads"); } public void testFilesList_LiveUpdate() throws Exception { initTestFiles(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich"); - bot.waitForDocument("Ham & Cheese.sandwich"); - bot.assertHasDocuments("file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich"); + bots.directory.waitForDocument("Ham & Cheese.sandwich"); + bots.directory.assertDocumentsPresent( + "file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich"); + } + + public void testCreateDirectory() throws Exception { + initTestFiles(); + + bots.main.openOverflowMenu(); + bots.main.menuNewFolder().click(); + bots.main.setDialogText("Kung Fu Panda"); + + bots.keyboard.pressEnter(); + + bots.directory.assertDocumentsPresent("Kung Fu Panda"); } public void testDeleteDocument() throws Exception { initTestFiles(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); - bot.clickDocument("file1.png"); + bots.directory.clickDocument("file1.png"); device.waitForIdle(); - bot.menuDelete().click(); + bots.main.menuDelete().click(); - bot.waitForDeleteSnackbar(); - assertFalse(bot.hasDocuments("file1.png")); + bots.directory.waitForDeleteSnackbar(); + bots.directory.assertDocumentsAbsent("file1.png"); - bot.waitForDeleteSnackbarGone(); - assertFalse(bot.hasDocuments("file1.png")); + bots.directory.waitForDeleteSnackbarGone(); + bots.directory.assertDocumentsAbsent("file1.png"); // Now delete from another root. - bot.openRoot(ROOT_1_ID); + bots.roots.openRoot(ROOT_1_ID); - bot.clickDocument("poodles.text"); + bots.directory.clickDocument("poodles.text"); device.waitForIdle(); - bot.menuDelete().click(); + bots.main.menuDelete().click(); - bot.waitForDeleteSnackbar(); - assertFalse(bot.hasDocuments("poodles.text")); + bots.directory.waitForDeleteSnackbar(); + bots.directory.assertDocumentsAbsent("poodles.text"); - bot.waitForDeleteSnackbarGone(); - assertFalse(bot.hasDocuments("poodles.text")); + bots.directory.waitForDeleteSnackbarGone(); + bots.directory.assertDocumentsAbsent("poodles.text"); } // Tests that pressing tab switches focus between the roots and directory listings. public void testKeyboard_tab() throws Exception { - bot.pressKey(KeyEvent.KEYCODE_TAB); - bot.assertHasFocus("com.android.documentsui:id/roots_list"); - bot.pressKey(KeyEvent.KEYCODE_TAB); - bot.assertHasFocus("com.android.documentsui:id/dir_list"); + bots.main.pressKey(KeyEvent.KEYCODE_TAB); + bots.roots.assertHasFocus(); + bots.main.pressKey(KeyEvent.KEYCODE_TAB); + bots.directory.assertHasFocus(); } // Tests that arrow keys do not switch focus away from the dir list. public void testKeyboard_arrowsDirList() throws Exception { for (int i = 0; i < 10; i++) { - bot.pressKey(KeyEvent.KEYCODE_DPAD_LEFT); - bot.assertHasFocus("com.android.documentsui:id/dir_list"); + bots.main.pressKey(KeyEvent.KEYCODE_DPAD_LEFT); + bots.directory.assertHasFocus(); } for (int i = 0; i < 10; i++) { - bot.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT); - bot.assertHasFocus("com.android.documentsui:id/dir_list"); + bots.main.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT); + bots.directory.assertHasFocus(); } } // Tests that arrow keys do not switch focus away from the roots list. public void testKeyboard_arrowsRootsList() throws Exception { - bot.pressKey(KeyEvent.KEYCODE_TAB); + bots.main.pressKey(KeyEvent.KEYCODE_TAB); for (int i = 0; i < 10; i++) { - bot.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT); - bot.assertHasFocus("com.android.documentsui:id/roots_list"); + bots.main.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT); + bots.roots.assertHasFocus(); } for (int i = 0; i < 10; i++) { - bot.pressKey(KeyEvent.KEYCODE_DPAD_LEFT); - bot.assertHasFocus("com.android.documentsui:id/roots_list"); + bots.main.pressKey(KeyEvent.KEYCODE_DPAD_LEFT); + bots.roots.assertHasFocus(); } } } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java index 770bc2c2fd4bf..b866033f647e2 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RenameDocumentUiTest.java @@ -23,8 +23,6 @@ import android.test.suitebuilder.annotation.LargeTest; @LargeTest public class RenameDocumentUiTest extends ActivityTest { - private static final String TAG = "RenamDocumentUiTest"; - private final String newName = "kitties.log"; public RenameDocumentUiTest() { @@ -35,125 +33,119 @@ public class RenameDocumentUiTest extends ActivityTest { public void setUp() throws Exception { super.setUp(); initTestFiles(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); } public void testRenameEnabled_SingleSelection() throws Exception { - bot.selectDocument(fileName1); - bot.openOverflowMenu(); - bot.assertMenuEnabled(R.string.menu_rename, true); + bots.directory.selectDocument(fileName1); + bots.main.openOverflowMenu(); + bots.main.assertMenuEnabled(R.string.menu_rename, true); // Dismiss more options window device.pressBack(); } public void testNoRenameSupport_SingleSelection() throws Exception { - bot.selectDocument(fileNameNoRename); - bot.openOverflowMenu(); - bot.assertMenuEnabled(R.string.menu_rename, false); + bots.directory.selectDocument(fileNameNoRename); + bots.main.openOverflowMenu(); + bots.main.assertMenuEnabled(R.string.menu_rename, false); // Dismiss more options window device.pressBack(); } public void testOneHasRenameSupport_MultipleSelection() throws Exception { - bot.selectDocument(fileName1); - bot.selectDocument(fileNameNoRename); - bot.openOverflowMenu(); - bot.assertMenuEnabled(R.string.menu_rename, false); + bots.directory.selectDocument(fileName1); + bots.directory.selectDocument(fileNameNoRename); + bots.main.openOverflowMenu(); + bots.main.assertMenuEnabled(R.string.menu_rename, false); // Dismiss more options window device.pressBack(); } public void testRenameDisabled_MultipleSelection() throws Exception { - bot.selectDocument(fileName1); - bot.selectDocument(fileName2); - bot.openOverflowMenu(); - bot.assertMenuEnabled(R.string.menu_rename, false); + bots.directory.selectDocument(fileName1); + bots.directory.selectDocument(fileName2); + bots.main.openOverflowMenu(); + bots.main.assertMenuEnabled(R.string.menu_rename, false); // Dismiss more options window device.pressBack(); } public void testRenameFile_OkButton() throws Exception { - bot.selectDocument(fileName1); - bot.openOverflowMenu(); - bot.openDialog(R.string.menu_rename); - bot.setDialogText(newName); + bots.directory.selectDocument(fileName1); + bots.main.openOverflowMenu(); + bots.main.menuRename().click(); + bots.main.setDialogText(newName); device.waitForIdle(TIMEOUT); - bot.findRenameDialogOkButton().click(); + bots.main.findRenameDialogOkButton().click(); device.waitForIdle(TIMEOUT); - bot.assertDocument(fileName1, false); - bot.assertDocument(newName, true); - bot.assertDocumentsCount(4); + bots.directory.assertDocumentsAbsent(fileName1); + bots.directory.assertDocumentsPresent(newName); + bots.directory.assertDocumentsCount(4); } public void testRenameFile_Enter() throws Exception { - bot.selectDocument(fileName1); - bot.openOverflowMenu(); - bot.openDialog(R.string.menu_rename); - bot.setDialogText(newName); + bots.directory.selectDocument(fileName1); + bots.main.openOverflowMenu(); + bots.main.menuRename().click(); + bots.main.setDialogText(newName); - pressEnter(); + bots.keyboard.pressEnter(); - bot.assertDocument(fileName1, false); - bot.assertDocument(newName, true); - bot.assertDocumentsCount(4); + bots.directory.assertDocumentsAbsent(fileName1); + bots.directory.assertDocumentsPresent(newName); + bots.directory.assertDocumentsCount(4); } public void testRenameFile_Cancel() throws Exception { - bot.selectDocument(fileName1); - bot.openOverflowMenu(); - bot.openDialog(R.string.menu_rename); - bot.setDialogText(newName); + bots.directory.selectDocument(fileName1); + bots.main.openOverflowMenu(); + bots.main.menuRename().click(); + bots.main.setDialogText(newName); device.waitForIdle(TIMEOUT); - bot.findRenameDialogCancelButton().click(); + bots.main.findRenameDialogCancelButton().click(); device.waitForIdle(TIMEOUT); - bot.assertDocument(fileName1, true); - bot.assertDocument(newName, false); - bot.assertDocumentsCount(4); + bots.directory.assertDocumentsPresent(fileName1); + bots.directory.assertDocumentsAbsent(newName); + bots.directory.assertDocumentsCount(4); } public void testRenameDir() throws Exception { String oldName = "Dir1"; String newName = "Dir123"; - bot.selectDocument(oldName); - bot.openOverflowMenu(); - bot.openDialog(R.string.menu_rename); - bot.setDialogText(newName); + bots.directory.selectDocument(oldName); + bots.main.openOverflowMenu(); + bots.main.menuRename().click(); + bots.main.setDialogText(newName); - pressEnter(); + bots.keyboard.pressEnter(); - bot.assertDocument(oldName, false); - bot.assertDocument(newName, true); - bot.assertDocumentsCount(4); + bots.directory.assertDocumentsAbsent(oldName); + bots.directory.assertDocumentsPresent(newName); + bots.directory.assertDocumentsCount(4); } public void testRename_NameExists() throws Exception { // Check that document with the new name exists - bot.assertDocument(fileName2, true); - bot.selectDocument(fileName1); - bot.openOverflowMenu(); - bot.openDialog(R.string.menu_rename); - bot.setDialogText(fileName2); + bots.directory.assertDocumentsPresent(fileName2); + bots.directory.selectDocument(fileName1); + bots.main.openOverflowMenu(); + bots.main.menuRename().click(); + bots.main.setDialogText(fileName2); - pressEnter(); + bots.keyboard.pressEnter(); - bot.assertSnackbar(R.string.rename_error); - bot.assertDocument(fileName1, true); - bot.assertDocument(fileName2, true); - bot.assertDocumentsCount(4); - } - - private void pressEnter() { - device.waitForIdle(TIMEOUT); - device.pressEnter(); - device.waitForIdle(TIMEOUT); + bots.directory.assertSnackbar(R.string.rename_error); + bots.directory.assertDocumentsPresent(fileName1); + bots.directory.assertDocumentsPresent(fileName2); + bots.directory.assertDocumentsCount(4); } } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java similarity index 68% rename from packages/DocumentsUI/tests/src/com/android/documentsui/RootUiTest.java rename to packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java index 1d1d3b5abd644..dc41a2c4474b3 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootUiTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsUiTest.java @@ -18,19 +18,14 @@ package com.android.documentsui; import static com.android.documentsui.StubProvider.ROOT_0_ID; -import android.support.test.uiautomator.Configurator; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiObjectNotFoundException; -import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.LargeTest; -import android.view.MotionEvent; @LargeTest -public class RootUiTest extends ActivityTest { +public class RootsUiTest extends ActivityTest { private static final String TAG = "RootUiTest"; - public RootUiTest() { + public RootsUiTest() { super(FilesActivity.class); } @@ -38,14 +33,14 @@ public class RootUiTest extends ActivityTest { public void setUp() throws Exception { super.setUp(); initTestFiles(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); } public void testRootTapped_GoToRootFromChildDir() throws Exception { - bot.openDocument(dirName1); - bot.assertWindowTitle(dirName1); - bot.openRoot(ROOT_0_ID); - bot.assertWindowTitle(ROOT_0_ID); + bots.directory.openDocument(dirName1); + bots.main.assertWindowTitle(dirName1); + bots.roots.openRoot(ROOT_0_ID); + bots.main.assertWindowTitle(ROOT_0_ID); assertDefaultContentOfTestDir0(); } } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java index b8d8795d864ce..478c70ca94c3b 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/SearchViewUiTest.java @@ -24,61 +24,59 @@ import android.test.suitebuilder.annotation.LargeTest; @LargeTest public class SearchViewUiTest extends ActivityTest { - private static final String TAG = "SearchViewUiTest"; - public SearchViewUiTest() { super(FilesActivity.class); } public void testSearchView_ExpandsOnClick() throws Exception { - bot.openSearchView(); - bot.assertSearchTextFiledAndIcon(true, false); + bots.main.openSearchView(); + bots.main.assertSearchTextFiledAndIcon(true, false); } public void testSearchView_CollapsesOnBack() throws Exception { - bot.openSearchView(); + bots.main.openSearchView(); device.pressBack(); - bot.assertSearchTextFiledAndIcon(false, true); + bots.main.assertSearchTextFiledAndIcon(false, true); } public void testSearchView_ClearsTextOnBack() throws Exception { String query = "file2"; - bot.openSearchView(); - bot.setSearchQuery(query); + bots.main.openSearchView(); + bots.main.setSearchQuery(query); device.pressBack(); - bot.assertSearchTextFiledAndIcon(false, true); + bots.main.assertSearchTextFiledAndIcon(false, true); } public void testSearch_ResultsFound() throws Exception { initTestFiles(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); assertDefaultContentOfTestDir0(); String query = "file1"; - bot.openSearchView(); - bot.setSearchQuery(query); - bot.assertSearchTextField(true, query); + bots.main.openSearchView(); + bots.main.setSearchQuery(query); + bots.main.assertSearchTextField(true, query); device.pressEnter(); - bot.assertDocumentsCountOnList(true, 2); - bot.assertHasDocuments(fileName1, fileName2); + bots.directory.assertDocumentsCountOnList(true, 2); + bots.directory.assertDocumentsPresent(fileName1, fileName2); - bot.assertSearchTextField(false, query); + bots.main.assertSearchTextField(false, query); } public void testSearchResultsFound_ClearsOnBack() throws Exception { initTestFiles(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); assertDefaultContentOfTestDir0(); String query = fileName1; - bot.openSearchView(); - bot.setSearchQuery(query); + bots.main.openSearchView(); + bots.main.setSearchQuery(query); device.pressEnter(); device.pressBack(); @@ -88,32 +86,32 @@ public class SearchViewUiTest extends ActivityTest { public void testSearch_NoResults() throws Exception { initTestFiles(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); assertDefaultContentOfTestDir0(); String query = "chocolate"; - bot.openSearchView(); - bot.setSearchQuery(query); + bots.main.openSearchView(); + bots.main.setSearchQuery(query); device.pressEnter(); - bot.assertDocumentsCountOnList(false, 0); + bots.directory.assertDocumentsCountOnList(false, 0); device.waitForIdle(); String msg = String.valueOf(context.getString(R.string.no_results)); - bot.assertMessageTextView(String.format(msg, "TEST_ROOT_0")); + bots.directory.assertMessageTextView(String.format(msg, "TEST_ROOT_0")); - bot.assertSearchTextField(false, query); + bots.main.assertSearchTextField(false, query); } public void testSearchNoResults_ClearsOnBack() throws Exception { initTestFiles(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); assertDefaultContentOfTestDir0(); String query = "chocolate"; - bot.openSearchView(); - bot.setSearchQuery(query); + bots.main.openSearchView(); + bots.main.setSearchQuery(query); device.pressEnter(); device.pressBack(); @@ -124,30 +122,30 @@ public class SearchViewUiTest extends ActivityTest { public void testSearchResultsFound_ClearsOnDirectoryChange() throws Exception { initTestFiles(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); assertDefaultContentOfTestDir0(); String query = fileName1; - bot.openSearchView(); - bot.setSearchQuery(query); + bots.main.openSearchView(); + bots.main.setSearchQuery(query); device.pressEnter(); - bot.openRoot(ROOT_1_ID); + bots.roots.openRoot(ROOT_1_ID); assertDefaultContentOfTestDir1(); - bot.openRoot(ROOT_0_ID); + bots.roots.openRoot(ROOT_0_ID); assertDefaultContentOfTestDir0(); } public void testSearchIconVisible_RootWithSearchSupport() throws Exception { - bot.openRoot(ROOT_0_ID); - bot.assertSearchTextFiledAndIcon(false, true); + bots.roots.openRoot(ROOT_0_ID); + bots.main.assertSearchTextFiledAndIcon(false, true); } public void testSearchIconHidden_RootNoSearchSupport() throws Exception { - bot.openRoot(ROOT_1_ID); - bot.assertSearchTextFiledAndIcon(false, false); + bots.roots.openRoot(ROOT_1_ID); + bots.main.assertSearchTextFiledAndIcon(false, false); } } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java deleted file mode 100644 index d2f84034593ca..0000000000000 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright (C) 2015 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; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; -import static junit.framework.Assert.assertFalse; - -import android.app.Activity; -import android.content.Context; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.BySelector; -import android.support.test.uiautomator.Configurator; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiObject2; -import android.support.test.uiautomator.UiObjectNotFoundException; -import android.support.test.uiautomator.UiScrollable; -import android.support.test.uiautomator.UiSelector; -import android.support.test.uiautomator.Until; -import android.util.Log; -import android.view.MotionEvent; -import android.view.inputmethod.InputMethodManager; - -import junit.framework.Assert; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.regex.Pattern; - -/** - * A test helper class that provides support for controlling DocumentsUI activities - * programmatically, and making assertions against the state of the UI. - */ -class UiBot { - public static final String TARGET_PKG = "com.android.documentsui"; - - private static final String TAG = "UiBot"; - private static final String LAUNCHER_PKG = "com.android.launcher"; - - private static final BySelector SNACK_DELETE = - By.desc(Pattern.compile("^Deleting [0-9]+ file.+")); - - private UiDevice mDevice; - private Context mContext; - private int mTimeout; - - public UiBot(UiDevice device, Context context, int timeout) { - mDevice = device; - mContext = context; - mTimeout = timeout; - } - - UiObject findRoot(String label) throws UiObjectNotFoundException { - final UiSelector rootsList = new UiSelector().resourceId( - "com.android.documentsui:id/container_roots").childSelector( - new UiSelector().resourceId("com.android.documentsui:id/roots_list")); - - // We might need to expand drawer if not visible - if (!new UiObject(rootsList).waitForExists(mTimeout)) { - Log.d(TAG, "Failed to find roots list; trying to expand"); - final UiSelector hamburger = new UiSelector().resourceId( - "com.android.documentsui:id/toolbar").childSelector( - new UiSelector().className("android.widget.ImageButton").clickable(true)); - new UiObject(hamburger).click(); - } - - // Wait for the first list item to appear - new UiObject(rootsList.childSelector(new UiSelector())).waitForExists(mTimeout); - - // Now scroll around to find our item - new UiScrollable(rootsList).scrollIntoView(new UiSelector().text(label)); - return new UiObject(rootsList.childSelector(new UiSelector().text(label))); - } - - void openRoot(String label) throws UiObjectNotFoundException { - findRoot(label).click(); - mDevice.waitForIdle(); - } - - void assertWindowTitle(String expected) { - // Turns out the title field on a window does not have - // an id associated with it at runtime (which confuses the hell out of me) - // In code we address this via "android.R.id.title". - UiObject2 o = find(By.text(expected)); - // It's a bit of a conceit that we then *assert* that the title - // is the value that we used to identify the UiObject2. - // If the preceeding lookup fails, this'll choke with an NPE. - // But given the issue described in the comment above, we're - // going to do it anyway. Because we shouldn't be looking up - // the uiobject by it's expected content :| - assertEquals(expected, o.getText()); - } - - void assertHasRoots(String... labels) throws UiObjectNotFoundException { - List missing = new ArrayList<>(); - for (String label : labels) { - if (!findRoot(label).exists()) { - missing.add(label); - } - } - if (!missing.isEmpty()) { - Assert.fail( - "Expected roots " + Arrays.asList(labels) + ", but missing " + missing); - } - } - - void assertMenuEnabled(int id, boolean enabled) { - UiObject2 menu= findMenuWithName(mContext.getString(id)); - assertNotNull(menu); - assertEquals(enabled, menu.isEnabled()); - } - - void assertDocumentsCount(int count) throws UiObjectNotFoundException { - UiObject docsList = findDocumentsList(); - assertEquals(count, docsList.getChildCount()); - } - - void assertDocumentsCount(String dir, int count) throws UiObjectNotFoundException { - openRoot(dir); - UiObject docsList = findDocumentsList(); - assertEquals(count, docsList.getChildCount()); - } - - void assertSearchTextField(boolean isFocused, String query) - throws UiObjectNotFoundException { - UiObject textField = findSearchViewTextField(); - UiObject searchIcon = findSearchViewIcon(); - - assertFalse(searchIcon.exists()); - assertTrue(textField.exists()); - assertEquals(isFocused, textField.isFocused()); - if(query != null) { - assertEquals(query, textField.getText()); - } - } - - void assertSearchTextFiledAndIcon(boolean searchTextFieldExists, boolean searchIconExists) { - assertEquals(searchTextFieldExists, findSearchViewTextField().exists()); - assertEquals(searchIconExists, findSearchViewIcon().exists()); - } - - void assertHasDocuments(String... labels) throws UiObjectNotFoundException { - List missing = new ArrayList<>(); - for (String label : labels) { - if (!findDocument(label).exists()) { - missing.add(label); - } - } - if (!missing.isEmpty()) { - Assert.fail( - "Expected documents " + Arrays.asList(labels) + ", but missing " + missing); - } - } - - void assertDocument(String name, boolean exists) throws UiObjectNotFoundException { - UiObject doc = findDocument(name); - assertEquals(exists, doc.exists()); - } - - void assertDocumentsCountOnList(boolean exists, int count) throws UiObjectNotFoundException { - UiObject docsList = findDocumentsList(); - assertEquals(exists, docsList.exists()); - if(docsList.exists()) { - assertEquals(count, docsList.getChildCount()); - } - } - - void assertMessageTextView(String message) throws UiObjectNotFoundException { - UiObject messageTextView = findMessageTextView(); - assertTrue(messageTextView.exists()); - - String msg = String.valueOf(message); - assertEquals(String.format(msg, "TEST_ROOT_0"), messageTextView.getText()); - - } - void assertSnackbar(int id) { - assertNotNull(getSnackbar(mContext.getString(id))); - } - - /** - * Asserts that the specified view or one of its descendents has focus. - */ - void assertHasFocus(String resourceName) { - UiObject2 candidate = mDevice.findObject(By.res(resourceName)); - assertNotNull("Expected " + resourceName + " to have focus, but it didn't.", - candidate.findObject(By.focused(true))); - } - - void openDocument(String label) throws UiObjectNotFoundException { - int toolType = Configurator.getInstance().getToolType(); - Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER); - UiObject doc = findDocument(label); - doc.click(); - Configurator.getInstance().setToolType(toolType); - } - - void clickDocument(String label) throws UiObjectNotFoundException { - findDocument(label).click(); - } - - void openSearchView() throws UiObjectNotFoundException { - UiObject searchView = findSearchView(); - searchView.click(); - assertTrue(searchView.exists()); - } - - void setSearchQuery(String query) throws UiObjectNotFoundException { - UiObject searchView = findSearchView(); - assertTrue(searchView.exists()); - UiObject searchTextField = findSearchViewTextField(); - searchTextField.setText(query); - assertSearchTextField(true, query); - } - - UiObject openOverflowMenu() throws UiObjectNotFoundException { - UiObject obj = findMenuMoreOptions(); - obj.click(); - mDevice.waitForIdle(mTimeout); - return obj; - } - - void openDialog(int id) { - UiObject2 menu= findMenuWithName(mContext.getString(id)); - assertNotNull(menu); - assertEquals(true, menu.isEnabled()); - menu.click(); - } - - void setDialogText(String text) throws UiObjectNotFoundException { - findDialogEditText().setText(text); - } - - UiObject selectDocument(String label) throws UiObjectNotFoundException { - UiObject doc = findDocument(label); - doc.longClick(); - return doc; - } - - UiObject2 getSnackbar(String message) { - return mDevice.wait(Until.findObject(By.text(message)), mTimeout); - } - - void waitForDeleteSnackbar() { - mDevice.wait(Until.findObject(SNACK_DELETE), mTimeout); - } - - void waitForDeleteSnackbarGone() { - // wait a little longer for snackbar to go away, as it disappears after a timeout. - mDevice.wait(Until.gone(SNACK_DELETE), mTimeout * 2); - } - - void waitForDocument(String label) throws UiObjectNotFoundException { - findDocument(label).waitForExists(mTimeout); - } - - void switchViewMode() { - UiObject2 mode = menuGridMode(); - if (mode != null) { - mode.click(); - } else { - menuListMode().click(); - } - } - - UiObject2 menuGridMode() { - // Note that we're using By.desc rather than By.res, because of b/25285770 - return find(By.desc("Grid view")); - } - - UiObject2 menuListMode() { - // Note that we're using By.desc rather than By.res, because of b/25285770 - return find(By.desc("List view")); - } - - UiObject2 menuDelete() { - return find(By.res("com.android.documentsui:id/menu_delete")); - } - - UiObject2 menuShare() { - return find(By.res("com.android.documentsui:id/menu_share")); - } - - private UiObject2 find(BySelector selector) { - mDevice.wait(Until.findObject(selector), mTimeout); - return mDevice.findObject(selector); - } - - private UiObject findObject(String resourceId) { - final UiSelector object = new UiSelector().resourceId(resourceId); - return mDevice.findObject(object); - } - - private UiObject findObject(String parentResourceId, String childResourceId) { - final UiSelector selector = new UiSelector() - .resourceId(parentResourceId) - .childSelector(new UiSelector().resourceId(childResourceId)); - return mDevice.findObject(selector); - } - - UiObject findDocument(String label) throws UiObjectNotFoundException { - final UiSelector docList = new UiSelector().resourceId( - "com.android.documentsui:id/container_directory").childSelector( - new UiSelector().resourceId("com.android.documentsui:id/dir_list")); - - // Wait for the first list item to appear - new UiObject(docList.childSelector(new UiSelector())).waitForExists(mTimeout); - - // new UiScrollable(docList).scrollIntoView(new UiSelector().text(label)); - return mDevice.findObject(docList.childSelector(new UiSelector().text(label))); - } - - boolean hasDocuments(String... labels) throws UiObjectNotFoundException { - for (String label : labels) { - if (!findDocument(label).exists()) { - return false; - } - } - return true; - } - - UiObject findDocumentsList() { - return findObject( - "com.android.documentsui:id/container_directory", - "com.android.documentsui:id/dir_list"); - } - - UiObject findSearchView() { - return findObject("com.android.documentsui:id/menu_search"); - } - - UiObject findSearchViewTextField() { - return findObject("com.android.documentsui:id/menu_search", "android:id/search_src_text"); - } - - UiObject findSearchViewIcon() { - return findObject("com.android.documentsui:id/menu_search", "android:id/search_button"); - } - - UiObject findMessageTextView() { - return findObject( - "com.android.documentsui:id/container_directory", - "com.android.documentsui:id/message"); - } - - UiObject findActionModeBar() { - return findObject("android:id/action_mode_bar"); - } - - UiObject findDialogEditText() { - return findObject("android:id/content", "android:id/text1"); - } - - UiObject findRenameDialogOkButton() { - return findObject("android:id/content", "android:id/button1"); - } - - UiObject findRenameDialogCancelButton() { - return findObject("android:id/content", "android:id/button2"); - } - - UiObject findMenuLabelWithName(String label) { - UiSelector selector = new UiSelector().text(label); - return mDevice.findObject(selector); - } - - UiObject2 findMenuWithName(String label) { - List menuItems = mDevice.findObjects(By.clazz("android.widget.LinearLayout")); - Iterator it = menuItems.iterator(); - - UiObject2 menuItem = null; - while(it.hasNext()) { - menuItem = it.next(); - UiObject2 text = menuItem.findObject(By.text(label)); - if(text != null) { - break; - } - } - return menuItem; - } - - UiObject findMenuMoreOptions() { - UiSelector selector = new UiSelector().className("android.widget.ImageButton") - .descriptionContains("More options"); - //TODO: use the system string ? android.R.string.action_menu_overflow_description - return mDevice.findObject(selector); - } - - // Indirect way to detect the keyboard. - boolean isKeyboardPresent() { - InputMethodManager inputManager = (InputMethodManager) mContext - .getSystemService(Context.INPUT_METHOD_SERVICE); - return inputManager.isAcceptingText(); - } - - void dismissKeyboardIfPresent() { - if(isKeyboardPresent()) { - mDevice.pressBack(); - } - } - - void revealLauncher() { - mDevice.pressHome(); - mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), mTimeout); - } - - void revealApp() { - mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), mTimeout); - mDevice.waitForIdle(); - } - - void pressKey(int keyCode) { - mDevice.pressKeyCode(keyCode); - } -} diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BaseBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BaseBot.java new file mode 100644 index 0000000000000..1d2b47f2f286b --- /dev/null +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/BaseBot.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015 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.bots; + +import static junit.framework.Assert.assertNotNull; + +import android.content.Context; +import android.support.test.uiautomator.By; +import android.support.test.uiautomator.BySelector; +import android.support.test.uiautomator.UiDevice; +import android.support.test.uiautomator.UiObject; +import android.support.test.uiautomator.UiObject2; +import android.support.test.uiautomator.UiSelector; +import android.support.test.uiautomator.Until; + +/** + * A test helper class that provides support for controlling directory list + * and making assertions against the state of it. + */ +abstract class BaseBot { + final UiDevice mDevice; + final Context mContext; + final int mTimeout; + + BaseBot(UiDevice device, Context context, int timeout) { + mDevice = device; + mContext = context; + mTimeout = timeout; + } + + /** + * Asserts that the specified view or one of its descendents has focus. + */ + protected void assertHasFocus(String resourceName) { + UiObject2 candidate = mDevice.findObject(By.res(resourceName)); + assertNotNull("Expected " + resourceName + " to have focus, but it didn't.", + candidate.findObject(By.focused(true))); + } + + protected UiObject2 find(BySelector selector) { + mDevice.wait(Until.findObject(selector), mTimeout); + return mDevice.findObject(selector); + } + + protected UiObject findObject(String resourceId) { + final UiSelector object = new UiSelector().resourceId(resourceId); + return mDevice.findObject(object); + } + + protected UiObject findObject(String parentResourceId, String childResourceId) { + final UiSelector selector = new UiSelector() + .resourceId(parentResourceId) + .childSelector(new UiSelector().resourceId(childResourceId)); + return mDevice.findObject(selector); + } + + protected void waitForIdle() { + mDevice.waitForIdle(mTimeout); + } +} diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java new file mode 100644 index 0000000000000..da9f9c30261a4 --- /dev/null +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/DirectoryListBot.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2015 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.bots; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; + +import android.content.Context; +import android.support.test.uiautomator.By; +import android.support.test.uiautomator.BySelector; +import android.support.test.uiautomator.Configurator; +import android.support.test.uiautomator.UiDevice; +import android.support.test.uiautomator.UiObject; +import android.support.test.uiautomator.UiObject2; +import android.support.test.uiautomator.UiObjectNotFoundException; +import android.support.test.uiautomator.UiSelector; +import android.support.test.uiautomator.Until; +import android.view.MotionEvent; + +import junit.framework.Assert; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +/** + * A test helper class that provides support for controlling directory list + * and making assertions against the state of it. + */ +public class DirectoryListBot extends BaseBot { + private static final String DIR_LIST_ID = "com.android.documentsui:id/dir_list"; + + private static final BySelector SNACK_DELETE = + By.desc(Pattern.compile("^Deleting [0-9]+ file.+")); + + public DirectoryListBot(UiDevice device, Context context, int timeout) { + super(device, context, timeout); + } + + public void assertDocumentsCount(int count) throws UiObjectNotFoundException { + UiObject docsList = findDocumentsList(); + assertEquals(count, docsList.getChildCount()); + } + + public void assertDocumentsPresent(String... labels) throws UiObjectNotFoundException { + List absent = new ArrayList<>(); + for (String label : labels) { + if (!findDocument(label).exists()) { + absent.add(label); + } + } + if (!absent.isEmpty()) { + Assert.fail("Expected documents " + Arrays.asList(labels) + + ", but missing " + absent); + } + } + + public void assertDocumentsAbsent(String... labels) throws UiObjectNotFoundException { + List found = new ArrayList<>(); + for (String label : labels) { + if (findDocument(label).exists()) { + found.add(label); + } + } + if (!found.isEmpty()) { + Assert.fail("Expected documents not present" + Arrays.asList(labels) + + ", but present " + found); + } + } + + public void assertDocumentsCountOnList(boolean exists, int count) throws UiObjectNotFoundException { + UiObject docsList = findDocumentsList(); + assertEquals(exists, docsList.exists()); + if(docsList.exists()) { + assertEquals(count, docsList.getChildCount()); + } + } + + public void assertMessageTextView(String message) throws UiObjectNotFoundException { + UiObject messageTextView = findMessageTextView(); + assertTrue(messageTextView.exists()); + + String msg = String.valueOf(message); + assertEquals(String.format(msg, "TEST_ROOT_0"), messageTextView.getText()); + + } + + private UiObject findMessageTextView() { + return findObject( + "com.android.documentsui:id/container_directory", + "com.android.documentsui:id/message"); + } + + public void assertSnackbar(int id) { + assertNotNull(getSnackbar(mContext.getString(id))); + } + + public void openDocument(String label) throws UiObjectNotFoundException { + int toolType = Configurator.getInstance().getToolType(); + Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER); + UiObject doc = findDocument(label); + doc.click(); + Configurator.getInstance().setToolType(toolType); + } + + public void clickDocument(String label) throws UiObjectNotFoundException { + findDocument(label).click(); + } + + public UiObject selectDocument(String label) throws UiObjectNotFoundException { + UiObject doc = findDocument(label); + doc.longClick(); + return doc; + } + + public UiObject2 getSnackbar(String message) { + return mDevice.wait(Until.findObject(By.text(message)), mTimeout); + } + + public void waitForDeleteSnackbar() { + mDevice.wait(Until.findObject(SNACK_DELETE), mTimeout); + } + + public void waitForDeleteSnackbarGone() { + // wait a little longer for snackbar to go away, as it disappears after a timeout. + mDevice.wait(Until.gone(SNACK_DELETE), mTimeout * 2); + } + + public void waitForDocument(String label) throws UiObjectNotFoundException { + findDocument(label).waitForExists(mTimeout); + } + + public UiObject findDocument(String label) throws UiObjectNotFoundException { + final UiSelector docList = new UiSelector().resourceId( + "com.android.documentsui:id/container_directory").childSelector( + new UiSelector().resourceId(DIR_LIST_ID)); + + // Wait for the first list item to appear + new UiObject(docList.childSelector(new UiSelector())).waitForExists(mTimeout); + + // new UiScrollable(docList).scrollIntoView(new UiSelector().text(label)); + return mDevice.findObject(docList.childSelector(new UiSelector().text(label))); + } + + public boolean hasDocuments(String... labels) throws UiObjectNotFoundException { + for (String label : labels) { + if (!findDocument(label).exists()) { + return false; + } + } + return true; + } + + private UiObject findDocumentsList() { + return findObject( + "com.android.documentsui:id/container_directory", + DIR_LIST_ID); + } + + public void assertHasFocus() { + assertHasFocus(DIR_LIST_ID); + } +} diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/KeyboardBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/KeyboardBot.java new file mode 100644 index 0000000000000..4c47cfacac726 --- /dev/null +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/KeyboardBot.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2015 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.bots; + +import android.content.Context; +import android.support.test.uiautomator.UiDevice; +import android.view.inputmethod.InputMethodManager; + +/** + * A test helper class that provides support for keyboard manipulation. + */ +public class KeyboardBot extends BaseBot { + + public KeyboardBot(UiDevice device, Context context, int timeout) { + super(device, context, timeout); + } + + public void dismissKeyboardIfPresent() { + if(isKeyboardPresent()) { + mDevice.pressBack(); + } + } + + // Indirect way to detect the keyboard. + private boolean isKeyboardPresent() { + InputMethodManager inputManager = (InputMethodManager) mContext + .getSystemService(Context.INPUT_METHOD_SERVICE); + return inputManager.isAcceptingText(); + } + + public void pressEnter() { + waitForIdle(); + mDevice.pressEnter(); + waitForIdle(); + } +} diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java new file mode 100644 index 0000000000000..356fd01957e6e --- /dev/null +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/RootsListBot.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 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.bots; + +import android.content.Context; +import android.support.test.uiautomator.UiDevice; +import android.support.test.uiautomator.UiObject; +import android.support.test.uiautomator.UiObjectNotFoundException; +import android.support.test.uiautomator.UiScrollable; +import android.support.test.uiautomator.UiSelector; +import android.util.Log; + +import junit.framework.Assert; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A test helper class that provides support for controlling and asserting against + * the roots list drawer. + */ +public class RootsListBot extends BaseBot { + private static final String ROOTS_LIST_ID = "com.android.documentsui:id/roots_list"; + private static final String TAG = "RootsListBot"; + + public RootsListBot(UiDevice device, Context context, int timeout) { + super(device, context, timeout); + } + + private UiObject findRoot(String label) throws UiObjectNotFoundException { + final UiSelector rootsList = new UiSelector().resourceId( + "com.android.documentsui:id/container_roots").childSelector( + new UiSelector().resourceId(ROOTS_LIST_ID)); + + // We might need to expand drawer if not visible + if (!new UiObject(rootsList).waitForExists(mTimeout)) { + Log.d(TAG, "Failed to find roots list; trying to expand"); + final UiSelector hamburger = new UiSelector().resourceId( + "com.android.documentsui:id/toolbar").childSelector( + new UiSelector().className("android.widget.ImageButton").clickable(true)); + new UiObject(hamburger).click(); + } + + // Wait for the first list item to appear + new UiObject(rootsList.childSelector(new UiSelector())).waitForExists(mTimeout); + + // Now scroll around to find our item + new UiScrollable(rootsList).scrollIntoView(new UiSelector().text(label)); + return new UiObject(rootsList.childSelector(new UiSelector().text(label))); + } + + public void openRoot(String label) throws UiObjectNotFoundException { + findRoot(label).click(); + mDevice.waitForIdle(); + } + + public void assertHasRoots(String... labels) throws UiObjectNotFoundException { + List missing = new ArrayList<>(); + for (String label : labels) { + if (!findRoot(label).exists()) { + missing.add(label); + } + } + if (!missing.isEmpty()) { + Assert.fail( + "Expected roots " + Arrays.asList(labels) + ", but missing " + missing); + } + } + + public void assertHasFocus() { + assertHasFocus(ROOTS_LIST_ID); + } +} diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java new file mode 100644 index 0000000000000..fe2a3c3209872 --- /dev/null +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2015 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.bots; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; + +import android.content.Context; +import android.support.test.uiautomator.By; +import android.support.test.uiautomator.UiDevice; +import android.support.test.uiautomator.UiObject; +import android.support.test.uiautomator.UiObject2; +import android.support.test.uiautomator.UiObjectNotFoundException; +import android.support.test.uiautomator.UiSelector; +import android.support.test.uiautomator.Until; + +import com.android.documentsui.R; + +import java.util.Iterator; +import java.util.List; + +/** + * A test helper class that provides support for controlling DocumentsUI activities + * programmatically, and making assertions against the state of the UI. + * + *

Support for working directly with Roots and Directory view can be found + * in the respective bots. + */ +public class UiBot extends BaseBot { + public static final String TARGET_PKG = "com.android.documentsui"; + private static final String LAUNCHER_PKG = "com.android.launcher"; + + public UiBot(UiDevice device, Context context, int timeout) { + super(device, context, timeout); + } + + public void assertWindowTitle(String expected) { + // Turns out the title field on a window does not have + // an id associated with it at runtime (which confuses the hell out of me) + // In code we address this via "android.R.id.title". + UiObject2 o = find(By.text(expected)); + // It's a bit of a conceit that we then *assert* that the title + // is the value that we used to identify the UiObject2. + // If the preceeding lookup fails, this'll choke with an NPE. + // But given the issue described in the comment above, we're + // going to do it anyway. Because we shouldn't be looking up + // the uiobject by it's expected content :| + assertEquals(expected, o.getText()); + } + + public void assertMenuEnabled(int id, boolean enabled) { + UiObject2 menu= findMenuWithName(mContext.getString(id)); + assertNotNull(menu); + assertEquals(enabled, menu.isEnabled()); + } + + public void assertSearchTextField(boolean isFocused, String query) + throws UiObjectNotFoundException { + UiObject textField = findSearchViewTextField(); + UiObject searchIcon = findSearchViewIcon(); + + assertFalse(searchIcon.exists()); + assertTrue(textField.exists()); + assertEquals(isFocused, textField.isFocused()); + if(query != null) { + assertEquals(query, textField.getText()); + } + } + + public void assertSearchTextFiledAndIcon(boolean searchTextFieldExists, boolean searchIconExists) { + assertEquals(searchTextFieldExists, findSearchViewTextField().exists()); + assertEquals(searchIconExists, findSearchViewIcon().exists()); + } + + public void openSearchView() throws UiObjectNotFoundException { + UiObject searchView = findSearchView(); + searchView.click(); + assertTrue(searchView.exists()); + } + + public void setSearchQuery(String query) throws UiObjectNotFoundException { + UiObject searchView = findSearchView(); + assertTrue(searchView.exists()); + UiObject searchTextField = findSearchViewTextField(); + searchTextField.setText(query); + assertSearchTextField(true, query); + } + + public UiObject openOverflowMenu() throws UiObjectNotFoundException { + UiObject obj = findMenuMoreOptions(); + obj.click(); + mDevice.waitForIdle(mTimeout); + return obj; + } + + public void setDialogText(String text) throws UiObjectNotFoundException { + findDialogEditText().setText(text); + } + + void switchViewMode() { + UiObject2 mode = menuGridMode(); + if (mode != null) { + mode.click(); + } else { + menuListMode().click(); + } + } + + UiObject2 menuGridMode() { + // Note that we're using By.desc rather than By.res, because of b/25285770 + return find(By.desc("Grid view")); + } + + UiObject2 menuListMode() { + // Note that we're using By.desc rather than By.res, because of b/25285770 + return find(By.desc("List view")); + } + + public UiObject2 menuDelete() { + return find(By.res("com.android.documentsui:id/menu_delete")); + } + + public UiObject2 menuShare() { + return find(By.res("com.android.documentsui:id/menu_share")); + } + + public UiObject2 menuRename() { + return findMenuWithName(mContext.getString(R.string.menu_rename)); + } + + public UiObject2 menuNewFolder() { + return findMenuWithName(mContext.getString(R.string.menu_create_dir)); + } + + UiObject findSearchView() { + return findObject("com.android.documentsui:id/menu_search"); + } + + UiObject findSearchViewTextField() { + return findObject("com.android.documentsui:id/menu_search", "android:id/search_src_text"); + } + + UiObject findSearchViewIcon() { + return findObject("com.android.documentsui:id/menu_search", "android:id/search_button"); + } + + UiObject findActionModeBar() { + return findObject("android:id/action_mode_bar"); + } + + public UiObject findDialogEditText() { + return findObject("android:id/content", "android:id/text1"); + } + + public UiObject findRenameDialogOkButton() { + return findObject("android:id/content", "android:id/button1"); + } + + public UiObject findRenameDialogCancelButton() { + return findObject("android:id/content", "android:id/button2"); + } + + UiObject findMenuLabelWithName(String label) { + UiSelector selector = new UiSelector().text(label); + return mDevice.findObject(selector); + } + + UiObject2 findMenuWithName(String label) { + List menuItems = mDevice.findObjects(By.clazz("android.widget.LinearLayout")); + Iterator it = menuItems.iterator(); + + UiObject2 menuItem = null; + while(it.hasNext()) { + menuItem = it.next(); + UiObject2 text = menuItem.findObject(By.text(label)); + if(text != null) { + break; + } + } + return menuItem; + } + + UiObject findMenuMoreOptions() { + UiSelector selector = new UiSelector().className("android.widget.ImageButton") + .descriptionContains("More options"); + //TODO: use the system string ? android.R.string.action_menu_overflow_description + return mDevice.findObject(selector); + } + + public void revealLauncher() { + mDevice.pressHome(); + mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), mTimeout); + } + + public void revealApp() { + mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), mTimeout); + mDevice.waitForIdle(); + } + + public void pressKey(int keyCode) { + mDevice.pressKeyCode(keyCode); + } +}