1c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski/* 2c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * Copyright (C) 2016 The Android Open Source Project 3c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * 4c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * Licensed under the Apache License, Version 2.0 (the "License"); 5c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * you may not use this file except in compliance with the License. 6c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * You may obtain a copy of the License at 7c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * 8c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * http://www.apache.org/licenses/LICENSE-2.0 9c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * 10c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * Unless required by applicable law or agreed to in writing, software 11c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * distributed under the License is distributed on an "AS IS" BASIS, 12c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * See the License for the specific language governing permissions and 14c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * limitations under the License. 15c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski */ 16c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 17c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskipackage com.android.documentsui; 18c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 19c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport static com.android.documentsui.StubProvider.DEFAULT_AUTHORITY; 20c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport static com.android.documentsui.StubProvider.ROOT_0_ID; 21c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport static com.android.documentsui.StubProvider.ROOT_1_ID; 22c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 23b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronskaimport android.annotation.Nullable; 24c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.app.Activity; 25c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.content.ContentProviderClient; 26c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.content.ContentResolver; 27c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.content.Context; 28c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.content.Intent; 29c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.os.RemoteException; 30c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.provider.DocumentsContract.Document; 31c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.support.test.uiautomator.Configurator; 32c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.support.test.uiautomator.UiDevice; 33c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.support.test.uiautomator.UiObjectNotFoundException; 34c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.test.ActivityInstrumentationTestCase2; 35ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewskiimport android.util.Log; 36c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport android.view.MotionEvent; 37c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 38ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewskiimport com.android.documentsui.BaseActivity; 39ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewskiimport com.android.documentsui.EventListener; 40b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKayimport com.android.documentsui.bots.DirectoryListBot; 41b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKayimport com.android.documentsui.bots.KeyboardBot; 42b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKayimport com.android.documentsui.bots.RootsListBot; 43b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKayimport com.android.documentsui.bots.UiBot; 44c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskiimport com.android.documentsui.model.RootInfo; 45c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 46c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski/** 47c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * Provides basic test environment for UI tests: 48c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * - Launches activity 49c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * - Creates and gives access to test root directories and test files 50c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski * - Cleans up the test environment 51c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski */ 52c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewskipublic abstract class ActivityTest<T extends Activity> extends ActivityInstrumentationTestCase2<T> { 53c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 54c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski static final int TIMEOUT = 5000; 55c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 56c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski // Testing files. For custom ones, override initTestFiles(). 57c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public static final String dirName1 = "Dir1"; 58c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public static final String fileName1 = "file1.log"; 59c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public static final String fileName2 = "file12.png"; 60c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public static final String fileName3 = "anotherFile0.log"; 61c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public static final String fileName4 = "poodles.text"; 62c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public static final String fileNameNoRename = "NO_RENAMEfile.txt"; 63c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 64b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay public Bots bots; 65c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public UiDevice device; 66c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public Context context; 67c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 68c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public RootInfo rootDir0; 69c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public RootInfo rootDir1; 70c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski ContentResolver mResolver; 71c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski DocumentsProviderHelper mDocsHelper; 72c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski ContentProviderClient mClient; 73c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 74c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public ActivityTest(Class<T> activityClass) { 75c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski super(activityClass); 76c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski } 77c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 78b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska /* 79b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska * Returns the root that will be opened within the activity. 80b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska * By default tests are started with one of the test roots. 81b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska * Override the method if you want to open different root on start. 82b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska * @return Root that will be opened. Return null if you want to open activity's default root. 83b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska */ 84b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska @Nullable 85b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska protected RootInfo getInitialRoot() { 86b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska return rootDir0; 87b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska } 88b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska 89ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski /** 90ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski * Returns the authority of the testing provider begin used. 91ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski * By default it's StubProvider's authority. 92ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski * @return Authority of the provider. 93ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski */ 94ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski protected String getTestingProviderAuthority() { 95ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski return DEFAULT_AUTHORITY; 96ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski } 97ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski 98ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski /** 99ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski * Resolves testing roots. 100ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski */ 101ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski protected void setupTestingRoots() throws RemoteException { 102ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski rootDir0 = mDocsHelper.getRoot(ROOT_0_ID); 103ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski rootDir1 = mDocsHelper.getRoot(ROOT_1_ID); 104ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski } 105ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski 106c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski @Override 107c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public void setUp() throws Exception { 108c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski device = UiDevice.getInstance(getInstrumentation()); 109c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski // NOTE: Must be the "target" context, else security checks in content provider will fail. 110c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski context = getInstrumentation().getTargetContext(); 111b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay 112b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay bots = new Bots(device, context, TIMEOUT); 113c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 114c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE); 115c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 116c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski mResolver = context.getContentResolver(); 117ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski mClient = mResolver.acquireUnstableContentProviderClient(getTestingProviderAuthority()); 118ae6d6b494c2f5837889ebe8cbd50d6782697884fTomasz Mikolajewski mDocsHelper = new DocumentsProviderHelper(getTestingProviderAuthority(), mClient); 119c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 120cf057efaff07fb22e2d4424e87f8ac1800c23afcTomasz Mikolajewski setupTestingRoots(); 121cf057efaff07fb22e2d4424e87f8ac1800c23afcTomasz Mikolajewski 122c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski launchActivity(); 123c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski resetStorage(); 124c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski } 125c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 126c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski @Override 127c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski public void tearDown() throws Exception { 128c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski mClient.release(); 129c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski super.tearDown(); 130c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski } 131c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 132c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski void launchActivity() { 133c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski final Intent intent = context.getPackageManager().getLaunchIntentForPackage( 134c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski UiBot.TARGET_PKG); 135c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); 136b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska if (getInitialRoot() != null) { 137b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska intent.setData(getInitialRoot().getUri()); 138b9eeee154339ba3a69bb9f822bd49b8094f51960Aga Wronska } 139c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski setActivityIntent(intent); 140c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski getActivity(); // Launch the activity. 141c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski } 142c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 143c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski void resetStorage() throws RemoteException { 144c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski mClient.call("clear", null, null); 145c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski device.waitForIdle(); 146c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski } 147c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 148c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski void initTestFiles() throws RemoteException { 149c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski mDocsHelper.createFolder(rootDir0, dirName1); 150c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski mDocsHelper.createDocument(rootDir0, "text/plain", fileName1); 151c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski mDocsHelper.createDocument(rootDir0, "image/png", fileName2); 152c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski mDocsHelper.createDocumentWithFlags(rootDir0.documentId, "text/plain", fileNameNoRename, 153c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski Document.FLAG_SUPPORTS_WRITE); 154c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 155c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski mDocsHelper.createDocument(rootDir1, "text/plain", fileName3); 156c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski mDocsHelper.createDocument(rootDir1, "text/plain", fileName4); 157c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski } 158c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 159c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski void assertDefaultContentOfTestDir0() throws UiObjectNotFoundException { 160b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay bots.directory.assertDocumentsCount(4); 161b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay bots.directory.assertDocumentsPresent(fileName1, fileName2, dirName1, fileNameNoRename); 162c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski } 163c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski 164c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski void assertDefaultContentOfTestDir1() throws UiObjectNotFoundException { 165b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay bots.directory.assertDocumentsCount(2); 166b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay bots.directory.assertDocumentsPresent(fileName3, fileName4); 167b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay } 168b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay 169b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay /** 170b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay * Handy collection of bots for working with Files app. 171b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay */ 172b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay public static final class Bots { 173b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay public final UiBot main; 174b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay public final RootsListBot roots; 175b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay public final DirectoryListBot directory; 176b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay public final KeyboardBot keyboard; 177b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay 178b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay private Bots(UiDevice device, Context context, int timeout) { 179b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay this.main = new UiBot(device, context, TIMEOUT); 180b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay this.roots = new RootsListBot(device, context, TIMEOUT); 181b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay this.directory = new DirectoryListBot(device, context, TIMEOUT); 182b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay this.keyboard = new KeyboardBot(device, context, TIMEOUT); 183b9a20d10c948cf111b70981e08233ea97323fe6cSteve McKay } 184c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski } 185c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski} 186