Merge "Move directory and roots support to own ui bots." into nyc-dev
This commit is contained in:
@@ -317,6 +317,12 @@ public abstract class BaseActivity extends Activity
|
|||||||
CreateDirectoryFragment.show(getFragmentManager());
|
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.
|
* Returns true if a directory can be created in the current location.
|
||||||
* @return
|
* @return
|
||||||
@@ -331,11 +337,6 @@ public abstract class BaseActivity extends Activity
|
|||||||
&& !root.isDownloads();
|
&& !root.isDownloads();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDirectoryCreated(DocumentInfo doc) {
|
|
||||||
checkArgument(doc.isDirectory());
|
|
||||||
openContainerDocument(doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void openContainerDocument(DocumentInfo doc) {
|
void openContainerDocument(DocumentInfo doc) {
|
||||||
checkArgument(doc.isContainer());
|
checkArgument(doc.isContainer());
|
||||||
mState.pushDocument(doc);
|
mState.pushDocument(doc);
|
||||||
|
|||||||
@@ -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_OPEN_TREE;
|
||||||
import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION;
|
import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION;
|
||||||
import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
|
import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
|
||||||
|
import static com.android.internal.util.Preconditions.checkArgument;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
@@ -316,6 +317,12 @@ public class DocumentsActivity extends BaseActivity {
|
|||||||
.executeOnExecutor(getExecutorForCurrentDirectory());
|
.executeOnExecutor(getExecutorForCurrentDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onDirectoryCreated(DocumentInfo doc) {
|
||||||
|
checkArgument(doc.isDirectory());
|
||||||
|
openContainerDocument(doc);
|
||||||
|
}
|
||||||
|
|
||||||
void onSaveRequested(String mimeType, String displayName) {
|
void onSaveRequested(String mimeType, String displayName) {
|
||||||
new CreateFinishTask(this, mimeType, displayName)
|
new CreateFinishTask(this, mimeType, displayName)
|
||||||
.executeOnExecutor(getExecutorForCurrentDirectory());
|
.executeOnExecutor(getExecutorForCurrentDirectory());
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import android.net.Uri;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.provider.DocumentsContract;
|
import android.provider.DocumentsContract;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
|||||||
@@ -21,21 +21,22 @@ import static com.android.documentsui.StubProvider.ROOT_0_ID;
|
|||||||
import static com.android.documentsui.StubProvider.ROOT_1_ID;
|
import static com.android.documentsui.StubProvider.ROOT_1_ID;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Instrumentation;
|
|
||||||
import android.content.ContentProviderClient;
|
import android.content.ContentProviderClient;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.provider.DocumentsContract.Document;
|
import android.provider.DocumentsContract.Document;
|
||||||
import android.support.test.uiautomator.By;
|
|
||||||
import android.support.test.uiautomator.Configurator;
|
import android.support.test.uiautomator.Configurator;
|
||||||
import android.support.test.uiautomator.UiDevice;
|
import android.support.test.uiautomator.UiDevice;
|
||||||
import android.support.test.uiautomator.UiObjectNotFoundException;
|
import android.support.test.uiautomator.UiObjectNotFoundException;
|
||||||
import android.support.test.uiautomator.Until;
|
|
||||||
import android.test.ActivityInstrumentationTestCase2;
|
import android.test.ActivityInstrumentationTestCase2;
|
||||||
import android.view.MotionEvent;
|
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;
|
import com.android.documentsui.model.RootInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +57,7 @@ public abstract class ActivityTest<T extends Activity> extends ActivityInstrumen
|
|||||||
public static final String fileName4 = "poodles.text";
|
public static final String fileName4 = "poodles.text";
|
||||||
public static final String fileNameNoRename = "NO_RENAMEfile.txt";
|
public static final String fileNameNoRename = "NO_RENAMEfile.txt";
|
||||||
|
|
||||||
public UiBot bot;
|
public Bots bots;
|
||||||
public UiDevice device;
|
public UiDevice device;
|
||||||
public Context context;
|
public Context context;
|
||||||
|
|
||||||
@@ -76,10 +77,11 @@ public abstract class ActivityTest<T extends Activity> extends ActivityInstrumen
|
|||||||
device = UiDevice.getInstance(getInstrumentation());
|
device = UiDevice.getInstance(getInstrumentation());
|
||||||
// NOTE: Must be the "target" context, else security checks in content provider will fail.
|
// NOTE: Must be the "target" context, else security checks in content provider will fail.
|
||||||
context = getInstrumentation().getTargetContext();
|
context = getInstrumentation().getTargetContext();
|
||||||
bot = new UiBot(device, context, TIMEOUT);
|
|
||||||
|
bots = new Bots(device, context, TIMEOUT);
|
||||||
|
|
||||||
Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
|
Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
|
||||||
bot.revealLauncher();
|
bots.main.revealLauncher();
|
||||||
|
|
||||||
mResolver = context.getContentResolver();
|
mResolver = context.getContentResolver();
|
||||||
mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
|
mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
|
||||||
@@ -90,7 +92,7 @@ public abstract class ActivityTest<T extends Activity> extends ActivityInstrumen
|
|||||||
|
|
||||||
launchActivity();
|
launchActivity();
|
||||||
|
|
||||||
bot.revealApp();
|
bots.main.revealApp();
|
||||||
resetStorage();
|
resetStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,12 +127,31 @@ public abstract class ActivityTest<T extends Activity> extends ActivityInstrumen
|
|||||||
}
|
}
|
||||||
|
|
||||||
void assertDefaultContentOfTestDir0() throws UiObjectNotFoundException {
|
void assertDefaultContentOfTestDir0() throws UiObjectNotFoundException {
|
||||||
bot.assertDocumentsCount(ROOT_0_ID, 4);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
bot.assertHasDocuments(fileName1, fileName2, dirName1, fileNameNoRename);
|
bots.directory.assertDocumentsCount(4);
|
||||||
|
bots.directory.assertDocumentsPresent(fileName1, fileName2, dirName1, fileNameNoRename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertDefaultContentOfTestDir1() throws UiObjectNotFoundException {
|
void assertDefaultContentOfTestDir1() throws UiObjectNotFoundException {
|
||||||
bot.assertDocumentsCount(ROOT_1_ID, 2);
|
bots.roots.openRoot(ROOT_1_ID);
|
||||||
bot.assertHasDocuments(fileName3, fileName4);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,13 +52,13 @@ public class DownloadsActivityUiTest extends ActivityTest<DownloadsActivity> {
|
|||||||
public void testWindowTitle() throws Exception {
|
public void testWindowTitle() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
|
|
||||||
bot.assertWindowTitle(ROOT_0_ID);
|
bots.main.assertWindowTitle(ROOT_0_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFilesListed() throws Exception {
|
public void testFilesListed() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
|
|
||||||
bot.assertHasDocuments("file0.log", "file1.png", "file2.csv");
|
bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFilesList_LiveUpdate() throws Exception {
|
public void testFilesList_LiveUpdate() throws Exception {
|
||||||
@@ -66,30 +66,31 @@ public class DownloadsActivityUiTest extends ActivityTest<DownloadsActivity> {
|
|||||||
|
|
||||||
mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich");
|
mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich");
|
||||||
|
|
||||||
bot.waitForDocument("Ham & Cheese.sandwich");
|
bots.directory.waitForDocument("Ham & Cheese.sandwich");
|
||||||
bot.assertHasDocuments("file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
|
bots.directory.assertDocumentsPresent(
|
||||||
|
"file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDeleteDocument() throws Exception {
|
public void testDeleteDocument() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
|
|
||||||
bot.clickDocument("file1.png");
|
bots.directory.clickDocument("file1.png");
|
||||||
device.waitForIdle();
|
device.waitForIdle();
|
||||||
bot.menuDelete().click();
|
bots.main.menuDelete().click();
|
||||||
|
|
||||||
bot.waitForDeleteSnackbar();
|
bots.directory.waitForDeleteSnackbar();
|
||||||
assertFalse(bot.hasDocuments("file1.png"));
|
bots.directory.assertDocumentsAbsent("file1.png");
|
||||||
|
|
||||||
bot.waitForDeleteSnackbarGone();
|
bots.directory.waitForDeleteSnackbarGone();
|
||||||
assertFalse(bot.hasDocuments("file1.png"));
|
bots.directory.assertDocumentsAbsent("file1.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSupportsShare() throws Exception {
|
public void testSupportsShare() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
|
|
||||||
bot.clickDocument("file1.png");
|
bots.directory.clickDocument("file1.png");
|
||||||
device.waitForIdle();
|
device.waitForIdle();
|
||||||
assertNotNull(bot.menuShare());
|
assertNotNull(bots.main.menuShare());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testClosesOnBack() throws Exception {
|
public void testClosesOnBack() throws Exception {
|
||||||
|
|||||||
@@ -43,11 +43,11 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
|
|||||||
public void testRootsListed() throws Exception {
|
public void testRootsListed() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
|
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
|
|
||||||
// Should also have Drive, but that requires pre-configuration of devices
|
// Should also have Drive, but that requires pre-configuration of devices
|
||||||
// We omit for now.
|
// We omit for now.
|
||||||
bot.assertHasRoots(
|
bots.roots.assertHasRoots(
|
||||||
"Images",
|
"Images",
|
||||||
"Videos",
|
"Videos",
|
||||||
"Audio",
|
"Audio",
|
||||||
@@ -60,93 +60,106 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> {
|
|||||||
public void testFilesListed() throws Exception {
|
public void testFilesListed() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
|
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
bot.assertHasDocuments("file0.log", "file1.png", "file2.csv");
|
bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLoadsHomeDirectoryByDefault() throws Exception {
|
public void testLoadsHomeDirectoryByDefault() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
|
|
||||||
device.waitForIdle();
|
device.waitForIdle();
|
||||||
bot.assertWindowTitle("Documents");
|
bots.main.assertWindowTitle("Documents");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRootClickSetsWindowTitle() throws Exception {
|
public void testRootClickSetsWindowTitle() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
|
|
||||||
bot.openRoot("Downloads");
|
bots.roots.openRoot("Downloads");
|
||||||
bot.assertWindowTitle("Downloads");
|
bots.main.assertWindowTitle("Downloads");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFilesList_LiveUpdate() throws Exception {
|
public void testFilesList_LiveUpdate() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
|
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich");
|
mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich");
|
||||||
|
|
||||||
bot.waitForDocument("Ham & Cheese.sandwich");
|
bots.directory.waitForDocument("Ham & Cheese.sandwich");
|
||||||
bot.assertHasDocuments("file0.log", "file1.png", "file2.csv", "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 {
|
public void testDeleteDocument() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
|
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
|
|
||||||
bot.clickDocument("file1.png");
|
bots.directory.clickDocument("file1.png");
|
||||||
device.waitForIdle();
|
device.waitForIdle();
|
||||||
bot.menuDelete().click();
|
bots.main.menuDelete().click();
|
||||||
|
|
||||||
bot.waitForDeleteSnackbar();
|
bots.directory.waitForDeleteSnackbar();
|
||||||
assertFalse(bot.hasDocuments("file1.png"));
|
bots.directory.assertDocumentsAbsent("file1.png");
|
||||||
|
|
||||||
bot.waitForDeleteSnackbarGone();
|
bots.directory.waitForDeleteSnackbarGone();
|
||||||
assertFalse(bot.hasDocuments("file1.png"));
|
bots.directory.assertDocumentsAbsent("file1.png");
|
||||||
|
|
||||||
// Now delete from another root.
|
// 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();
|
device.waitForIdle();
|
||||||
bot.menuDelete().click();
|
bots.main.menuDelete().click();
|
||||||
|
|
||||||
bot.waitForDeleteSnackbar();
|
bots.directory.waitForDeleteSnackbar();
|
||||||
assertFalse(bot.hasDocuments("poodles.text"));
|
bots.directory.assertDocumentsAbsent("poodles.text");
|
||||||
|
|
||||||
bot.waitForDeleteSnackbarGone();
|
bots.directory.waitForDeleteSnackbarGone();
|
||||||
assertFalse(bot.hasDocuments("poodles.text"));
|
bots.directory.assertDocumentsAbsent("poodles.text");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that pressing tab switches focus between the roots and directory listings.
|
// Tests that pressing tab switches focus between the roots and directory listings.
|
||||||
public void testKeyboard_tab() throws Exception {
|
public void testKeyboard_tab() throws Exception {
|
||||||
bot.pressKey(KeyEvent.KEYCODE_TAB);
|
bots.main.pressKey(KeyEvent.KEYCODE_TAB);
|
||||||
bot.assertHasFocus("com.android.documentsui:id/roots_list");
|
bots.roots.assertHasFocus();
|
||||||
bot.pressKey(KeyEvent.KEYCODE_TAB);
|
bots.main.pressKey(KeyEvent.KEYCODE_TAB);
|
||||||
bot.assertHasFocus("com.android.documentsui:id/dir_list");
|
bots.directory.assertHasFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that arrow keys do not switch focus away from the dir list.
|
// Tests that arrow keys do not switch focus away from the dir list.
|
||||||
public void testKeyboard_arrowsDirList() throws Exception {
|
public void testKeyboard_arrowsDirList() throws Exception {
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
bot.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
|
bots.main.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
|
||||||
bot.assertHasFocus("com.android.documentsui:id/dir_list");
|
bots.directory.assertHasFocus();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
bot.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
|
bots.main.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
|
||||||
bot.assertHasFocus("com.android.documentsui:id/dir_list");
|
bots.directory.assertHasFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that arrow keys do not switch focus away from the roots list.
|
// Tests that arrow keys do not switch focus away from the roots list.
|
||||||
public void testKeyboard_arrowsRootsList() throws Exception {
|
public void testKeyboard_arrowsRootsList() throws Exception {
|
||||||
bot.pressKey(KeyEvent.KEYCODE_TAB);
|
bots.main.pressKey(KeyEvent.KEYCODE_TAB);
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
bot.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
|
bots.main.pressKey(KeyEvent.KEYCODE_DPAD_RIGHT);
|
||||||
bot.assertHasFocus("com.android.documentsui:id/roots_list");
|
bots.roots.assertHasFocus();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
bot.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
|
bots.main.pressKey(KeyEvent.KEYCODE_DPAD_LEFT);
|
||||||
bot.assertHasFocus("com.android.documentsui:id/roots_list");
|
bots.roots.assertHasFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ import android.test.suitebuilder.annotation.LargeTest;
|
|||||||
@LargeTest
|
@LargeTest
|
||||||
public class RenameDocumentUiTest extends ActivityTest<FilesActivity> {
|
public class RenameDocumentUiTest extends ActivityTest<FilesActivity> {
|
||||||
|
|
||||||
private static final String TAG = "RenamDocumentUiTest";
|
|
||||||
|
|
||||||
private final String newName = "kitties.log";
|
private final String newName = "kitties.log";
|
||||||
|
|
||||||
public RenameDocumentUiTest() {
|
public RenameDocumentUiTest() {
|
||||||
@@ -35,125 +33,119 @@ public class RenameDocumentUiTest extends ActivityTest<FilesActivity> {
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRenameEnabled_SingleSelection() throws Exception {
|
public void testRenameEnabled_SingleSelection() throws Exception {
|
||||||
bot.selectDocument(fileName1);
|
bots.directory.selectDocument(fileName1);
|
||||||
bot.openOverflowMenu();
|
bots.main.openOverflowMenu();
|
||||||
bot.assertMenuEnabled(R.string.menu_rename, true);
|
bots.main.assertMenuEnabled(R.string.menu_rename, true);
|
||||||
|
|
||||||
// Dismiss more options window
|
// Dismiss more options window
|
||||||
device.pressBack();
|
device.pressBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNoRenameSupport_SingleSelection() throws Exception {
|
public void testNoRenameSupport_SingleSelection() throws Exception {
|
||||||
bot.selectDocument(fileNameNoRename);
|
bots.directory.selectDocument(fileNameNoRename);
|
||||||
bot.openOverflowMenu();
|
bots.main.openOverflowMenu();
|
||||||
bot.assertMenuEnabled(R.string.menu_rename, false);
|
bots.main.assertMenuEnabled(R.string.menu_rename, false);
|
||||||
|
|
||||||
// Dismiss more options window
|
// Dismiss more options window
|
||||||
device.pressBack();
|
device.pressBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testOneHasRenameSupport_MultipleSelection() throws Exception {
|
public void testOneHasRenameSupport_MultipleSelection() throws Exception {
|
||||||
bot.selectDocument(fileName1);
|
bots.directory.selectDocument(fileName1);
|
||||||
bot.selectDocument(fileNameNoRename);
|
bots.directory.selectDocument(fileNameNoRename);
|
||||||
bot.openOverflowMenu();
|
bots.main.openOverflowMenu();
|
||||||
bot.assertMenuEnabled(R.string.menu_rename, false);
|
bots.main.assertMenuEnabled(R.string.menu_rename, false);
|
||||||
|
|
||||||
// Dismiss more options window
|
// Dismiss more options window
|
||||||
device.pressBack();
|
device.pressBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRenameDisabled_MultipleSelection() throws Exception {
|
public void testRenameDisabled_MultipleSelection() throws Exception {
|
||||||
bot.selectDocument(fileName1);
|
bots.directory.selectDocument(fileName1);
|
||||||
bot.selectDocument(fileName2);
|
bots.directory.selectDocument(fileName2);
|
||||||
bot.openOverflowMenu();
|
bots.main.openOverflowMenu();
|
||||||
bot.assertMenuEnabled(R.string.menu_rename, false);
|
bots.main.assertMenuEnabled(R.string.menu_rename, false);
|
||||||
|
|
||||||
// Dismiss more options window
|
// Dismiss more options window
|
||||||
device.pressBack();
|
device.pressBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRenameFile_OkButton() throws Exception {
|
public void testRenameFile_OkButton() throws Exception {
|
||||||
bot.selectDocument(fileName1);
|
bots.directory.selectDocument(fileName1);
|
||||||
bot.openOverflowMenu();
|
bots.main.openOverflowMenu();
|
||||||
bot.openDialog(R.string.menu_rename);
|
bots.main.menuRename().click();
|
||||||
bot.setDialogText(newName);
|
bots.main.setDialogText(newName);
|
||||||
|
|
||||||
device.waitForIdle(TIMEOUT);
|
device.waitForIdle(TIMEOUT);
|
||||||
bot.findRenameDialogOkButton().click();
|
bots.main.findRenameDialogOkButton().click();
|
||||||
device.waitForIdle(TIMEOUT);
|
device.waitForIdle(TIMEOUT);
|
||||||
|
|
||||||
bot.assertDocument(fileName1, false);
|
bots.directory.assertDocumentsAbsent(fileName1);
|
||||||
bot.assertDocument(newName, true);
|
bots.directory.assertDocumentsPresent(newName);
|
||||||
bot.assertDocumentsCount(4);
|
bots.directory.assertDocumentsCount(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRenameFile_Enter() throws Exception {
|
public void testRenameFile_Enter() throws Exception {
|
||||||
bot.selectDocument(fileName1);
|
bots.directory.selectDocument(fileName1);
|
||||||
bot.openOverflowMenu();
|
bots.main.openOverflowMenu();
|
||||||
bot.openDialog(R.string.menu_rename);
|
bots.main.menuRename().click();
|
||||||
bot.setDialogText(newName);
|
bots.main.setDialogText(newName);
|
||||||
|
|
||||||
pressEnter();
|
bots.keyboard.pressEnter();
|
||||||
|
|
||||||
bot.assertDocument(fileName1, false);
|
bots.directory.assertDocumentsAbsent(fileName1);
|
||||||
bot.assertDocument(newName, true);
|
bots.directory.assertDocumentsPresent(newName);
|
||||||
bot.assertDocumentsCount(4);
|
bots.directory.assertDocumentsCount(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRenameFile_Cancel() throws Exception {
|
public void testRenameFile_Cancel() throws Exception {
|
||||||
bot.selectDocument(fileName1);
|
bots.directory.selectDocument(fileName1);
|
||||||
bot.openOverflowMenu();
|
bots.main.openOverflowMenu();
|
||||||
bot.openDialog(R.string.menu_rename);
|
bots.main.menuRename().click();
|
||||||
bot.setDialogText(newName);
|
bots.main.setDialogText(newName);
|
||||||
|
|
||||||
device.waitForIdle(TIMEOUT);
|
device.waitForIdle(TIMEOUT);
|
||||||
bot.findRenameDialogCancelButton().click();
|
bots.main.findRenameDialogCancelButton().click();
|
||||||
device.waitForIdle(TIMEOUT);
|
device.waitForIdle(TIMEOUT);
|
||||||
|
|
||||||
bot.assertDocument(fileName1, true);
|
bots.directory.assertDocumentsPresent(fileName1);
|
||||||
bot.assertDocument(newName, false);
|
bots.directory.assertDocumentsAbsent(newName);
|
||||||
bot.assertDocumentsCount(4);
|
bots.directory.assertDocumentsCount(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRenameDir() throws Exception {
|
public void testRenameDir() throws Exception {
|
||||||
String oldName = "Dir1";
|
String oldName = "Dir1";
|
||||||
String newName = "Dir123";
|
String newName = "Dir123";
|
||||||
|
|
||||||
bot.selectDocument(oldName);
|
bots.directory.selectDocument(oldName);
|
||||||
bot.openOverflowMenu();
|
bots.main.openOverflowMenu();
|
||||||
bot.openDialog(R.string.menu_rename);
|
bots.main.menuRename().click();
|
||||||
bot.setDialogText(newName);
|
bots.main.setDialogText(newName);
|
||||||
|
|
||||||
pressEnter();
|
bots.keyboard.pressEnter();
|
||||||
|
|
||||||
bot.assertDocument(oldName, false);
|
bots.directory.assertDocumentsAbsent(oldName);
|
||||||
bot.assertDocument(newName, true);
|
bots.directory.assertDocumentsPresent(newName);
|
||||||
bot.assertDocumentsCount(4);
|
bots.directory.assertDocumentsCount(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRename_NameExists() throws Exception {
|
public void testRename_NameExists() throws Exception {
|
||||||
// Check that document with the new name exists
|
// Check that document with the new name exists
|
||||||
bot.assertDocument(fileName2, true);
|
bots.directory.assertDocumentsPresent(fileName2);
|
||||||
bot.selectDocument(fileName1);
|
bots.directory.selectDocument(fileName1);
|
||||||
bot.openOverflowMenu();
|
bots.main.openOverflowMenu();
|
||||||
bot.openDialog(R.string.menu_rename);
|
bots.main.menuRename().click();
|
||||||
bot.setDialogText(fileName2);
|
bots.main.setDialogText(fileName2);
|
||||||
|
|
||||||
pressEnter();
|
bots.keyboard.pressEnter();
|
||||||
|
|
||||||
bot.assertSnackbar(R.string.rename_error);
|
bots.directory.assertSnackbar(R.string.rename_error);
|
||||||
bot.assertDocument(fileName1, true);
|
bots.directory.assertDocumentsPresent(fileName1);
|
||||||
bot.assertDocument(fileName2, true);
|
bots.directory.assertDocumentsPresent(fileName2);
|
||||||
bot.assertDocumentsCount(4);
|
bots.directory.assertDocumentsCount(4);
|
||||||
}
|
|
||||||
|
|
||||||
private void pressEnter() {
|
|
||||||
device.waitForIdle(TIMEOUT);
|
|
||||||
device.pressEnter();
|
|
||||||
device.waitForIdle(TIMEOUT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,19 +18,14 @@ package com.android.documentsui;
|
|||||||
|
|
||||||
import static com.android.documentsui.StubProvider.ROOT_0_ID;
|
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.test.suitebuilder.annotation.LargeTest;
|
||||||
import android.view.MotionEvent;
|
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
public class RootUiTest extends ActivityTest<FilesActivity> {
|
public class RootsUiTest extends ActivityTest<FilesActivity> {
|
||||||
|
|
||||||
private static final String TAG = "RootUiTest";
|
private static final String TAG = "RootUiTest";
|
||||||
|
|
||||||
public RootUiTest() {
|
public RootsUiTest() {
|
||||||
super(FilesActivity.class);
|
super(FilesActivity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,14 +33,14 @@ public class RootUiTest extends ActivityTest<FilesActivity> {
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRootTapped_GoToRootFromChildDir() throws Exception {
|
public void testRootTapped_GoToRootFromChildDir() throws Exception {
|
||||||
bot.openDocument(dirName1);
|
bots.directory.openDocument(dirName1);
|
||||||
bot.assertWindowTitle(dirName1);
|
bots.main.assertWindowTitle(dirName1);
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
bot.assertWindowTitle(ROOT_0_ID);
|
bots.main.assertWindowTitle(ROOT_0_ID);
|
||||||
assertDefaultContentOfTestDir0();
|
assertDefaultContentOfTestDir0();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,61 +24,59 @@ import android.test.suitebuilder.annotation.LargeTest;
|
|||||||
@LargeTest
|
@LargeTest
|
||||||
public class SearchViewUiTest extends ActivityTest<FilesActivity> {
|
public class SearchViewUiTest extends ActivityTest<FilesActivity> {
|
||||||
|
|
||||||
private static final String TAG = "SearchViewUiTest";
|
|
||||||
|
|
||||||
public SearchViewUiTest() {
|
public SearchViewUiTest() {
|
||||||
super(FilesActivity.class);
|
super(FilesActivity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSearchView_ExpandsOnClick() throws Exception {
|
public void testSearchView_ExpandsOnClick() throws Exception {
|
||||||
bot.openSearchView();
|
bots.main.openSearchView();
|
||||||
bot.assertSearchTextFiledAndIcon(true, false);
|
bots.main.assertSearchTextFiledAndIcon(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSearchView_CollapsesOnBack() throws Exception {
|
public void testSearchView_CollapsesOnBack() throws Exception {
|
||||||
bot.openSearchView();
|
bots.main.openSearchView();
|
||||||
|
|
||||||
device.pressBack();
|
device.pressBack();
|
||||||
|
|
||||||
bot.assertSearchTextFiledAndIcon(false, true);
|
bots.main.assertSearchTextFiledAndIcon(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSearchView_ClearsTextOnBack() throws Exception {
|
public void testSearchView_ClearsTextOnBack() throws Exception {
|
||||||
String query = "file2";
|
String query = "file2";
|
||||||
bot.openSearchView();
|
bots.main.openSearchView();
|
||||||
bot.setSearchQuery(query);
|
bots.main.setSearchQuery(query);
|
||||||
|
|
||||||
device.pressBack();
|
device.pressBack();
|
||||||
|
|
||||||
bot.assertSearchTextFiledAndIcon(false, true);
|
bots.main.assertSearchTextFiledAndIcon(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSearch_ResultsFound() throws Exception {
|
public void testSearch_ResultsFound() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
assertDefaultContentOfTestDir0();
|
assertDefaultContentOfTestDir0();
|
||||||
|
|
||||||
String query = "file1";
|
String query = "file1";
|
||||||
bot.openSearchView();
|
bots.main.openSearchView();
|
||||||
bot.setSearchQuery(query);
|
bots.main.setSearchQuery(query);
|
||||||
bot.assertSearchTextField(true, query);
|
bots.main.assertSearchTextField(true, query);
|
||||||
|
|
||||||
device.pressEnter();
|
device.pressEnter();
|
||||||
|
|
||||||
bot.assertDocumentsCountOnList(true, 2);
|
bots.directory.assertDocumentsCountOnList(true, 2);
|
||||||
bot.assertHasDocuments(fileName1, fileName2);
|
bots.directory.assertDocumentsPresent(fileName1, fileName2);
|
||||||
|
|
||||||
bot.assertSearchTextField(false, query);
|
bots.main.assertSearchTextField(false, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSearchResultsFound_ClearsOnBack() throws Exception {
|
public void testSearchResultsFound_ClearsOnBack() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
assertDefaultContentOfTestDir0();
|
assertDefaultContentOfTestDir0();
|
||||||
|
|
||||||
String query = fileName1;
|
String query = fileName1;
|
||||||
bot.openSearchView();
|
bots.main.openSearchView();
|
||||||
bot.setSearchQuery(query);
|
bots.main.setSearchQuery(query);
|
||||||
|
|
||||||
device.pressEnter();
|
device.pressEnter();
|
||||||
device.pressBack();
|
device.pressBack();
|
||||||
@@ -88,32 +86,32 @@ public class SearchViewUiTest extends ActivityTest<FilesActivity> {
|
|||||||
|
|
||||||
public void testSearch_NoResults() throws Exception {
|
public void testSearch_NoResults() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
assertDefaultContentOfTestDir0();
|
assertDefaultContentOfTestDir0();
|
||||||
|
|
||||||
String query = "chocolate";
|
String query = "chocolate";
|
||||||
bot.openSearchView();
|
bots.main.openSearchView();
|
||||||
bot.setSearchQuery(query);
|
bots.main.setSearchQuery(query);
|
||||||
|
|
||||||
device.pressEnter();
|
device.pressEnter();
|
||||||
|
|
||||||
bot.assertDocumentsCountOnList(false, 0);
|
bots.directory.assertDocumentsCountOnList(false, 0);
|
||||||
|
|
||||||
device.waitForIdle();
|
device.waitForIdle();
|
||||||
String msg = String.valueOf(context.getString(R.string.no_results));
|
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 {
|
public void testSearchNoResults_ClearsOnBack() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
assertDefaultContentOfTestDir0();
|
assertDefaultContentOfTestDir0();
|
||||||
|
|
||||||
String query = "chocolate";
|
String query = "chocolate";
|
||||||
bot.openSearchView();
|
bots.main.openSearchView();
|
||||||
bot.setSearchQuery(query);
|
bots.main.setSearchQuery(query);
|
||||||
|
|
||||||
device.pressEnter();
|
device.pressEnter();
|
||||||
device.pressBack();
|
device.pressBack();
|
||||||
@@ -124,30 +122,30 @@ public class SearchViewUiTest extends ActivityTest<FilesActivity> {
|
|||||||
|
|
||||||
public void testSearchResultsFound_ClearsOnDirectoryChange() throws Exception {
|
public void testSearchResultsFound_ClearsOnDirectoryChange() throws Exception {
|
||||||
initTestFiles();
|
initTestFiles();
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
assertDefaultContentOfTestDir0();
|
assertDefaultContentOfTestDir0();
|
||||||
|
|
||||||
String query = fileName1;
|
String query = fileName1;
|
||||||
bot.openSearchView();
|
bots.main.openSearchView();
|
||||||
bot.setSearchQuery(query);
|
bots.main.setSearchQuery(query);
|
||||||
|
|
||||||
device.pressEnter();
|
device.pressEnter();
|
||||||
|
|
||||||
bot.openRoot(ROOT_1_ID);
|
bots.roots.openRoot(ROOT_1_ID);
|
||||||
assertDefaultContentOfTestDir1();
|
assertDefaultContentOfTestDir1();
|
||||||
|
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
assertDefaultContentOfTestDir0();
|
assertDefaultContentOfTestDir0();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSearchIconVisible_RootWithSearchSupport() throws Exception {
|
public void testSearchIconVisible_RootWithSearchSupport() throws Exception {
|
||||||
bot.openRoot(ROOT_0_ID);
|
bots.roots.openRoot(ROOT_0_ID);
|
||||||
bot.assertSearchTextFiledAndIcon(false, true);
|
bots.main.assertSearchTextFiledAndIcon(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSearchIconHidden_RootNoSearchSupport() throws Exception {
|
public void testSearchIconHidden_RootNoSearchSupport() throws Exception {
|
||||||
bot.openRoot(ROOT_1_ID);
|
bots.roots.openRoot(ROOT_1_ID);
|
||||||
bot.assertSearchTextFiledAndIcon(false, false);
|
bots.main.assertSearchTextFiledAndIcon(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<String> 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<String> 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<UiObject2> menuItems = mDevice.findObjects(By.clazz("android.widget.LinearLayout"));
|
|
||||||
Iterator<UiObject2> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<String> 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<String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<String> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
|
*
|
||||||
|
* <p>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<UiObject2> menuItems = mDevice.findObjects(By.clazz("android.widget.LinearLayout"));
|
||||||
|
Iterator<UiObject2> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user