1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.documentsui; 18 19 import android.app.Activity; 20 import android.app.UiAutomation; 21 import android.app.UiModeManager; 22 import android.content.ContentProviderClient; 23 import android.content.ContentResolver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.res.Configuration; 27 import android.os.Bundle; 28 import android.os.RemoteException; 29 import android.provider.DocumentsContract; 30 import android.provider.DocumentsContract.Document; 31 import android.support.test.uiautomator.Configurator; 32 import android.support.test.uiautomator.UiDevice; 33 import android.support.test.uiautomator.UiObjectNotFoundException; 34 import android.test.ActivityInstrumentationTestCase2; 35 import android.view.MotionEvent; 36 37 import com.android.documentsui.base.Features; 38 import com.android.documentsui.base.RootInfo; 39 import com.android.documentsui.base.UserId; 40 import com.android.documentsui.bots.Bots; 41 import com.android.documentsui.files.FilesActivity; 42 43 import javax.annotation.Nullable; 44 45 /** 46 * Provides basic test environment for UI tests: 47 * - Launches activity 48 * - Creates and gives access to test root directories and test files 49 * - Cleans up the test environment 50 */ 51 public abstract class ActivityTest<T extends Activity> extends ActivityInstrumentationTestCase2<T> { 52 53 static final int TIMEOUT = 5000; 54 static final int NIGHT_MODE_CHANGE_WAIT_TIME = 1000; 55 56 // Testing files. For custom ones, override initTestFiles(). 57 public static final String dirName1 = "Dir1"; 58 public static final String childDir1 = "ChildDir1"; 59 public static final String fileName1 = "file1.log"; 60 public static final String fileName2 = "file12.png"; 61 public static final String fileName3 = "anotherFile0.log"; 62 public static final String fileName4 = "poodles.text"; 63 public static final String fileNameNoRename = "NO_RENAMEfile.txt"; 64 65 public Bots bots; 66 public UiDevice device; 67 public Context context; 68 public UserId userId; 69 public UiAutomation automation; 70 71 public Features features; 72 public RootInfo rootDir0; 73 public RootInfo rootDir1; 74 protected ContentResolver mResolver; 75 protected DocumentsProviderHelper mDocsHelper; 76 protected ContentProviderClient mClient; 77 protected UiModeManager mUiModeManager; 78 ActivityTest(Class<T> activityClass)79 public ActivityTest(Class<T> activityClass) { 80 super(activityClass); 81 } 82 83 /* 84 * Returns the root that will be opened within the activity. 85 * By default tests are started with one of the test roots. 86 * Override the method if you want to open different root on start. 87 * @return Root that will be opened. Return null if you want to open activity's default root. 88 */ getInitialRoot()89 protected @Nullable RootInfo getInitialRoot() { 90 return rootDir0; 91 } 92 93 /** 94 * Returns the authority of the testing provider begin used. 95 * By default it's StubProvider's authority. 96 * @return Authority of the provider. 97 */ getTestingProviderAuthority()98 protected String getTestingProviderAuthority() { 99 return StubProvider.DEFAULT_AUTHORITY; 100 } 101 102 /** 103 * Resolves testing roots. 104 */ setupTestingRoots()105 protected void setupTestingRoots() throws RemoteException { 106 rootDir0 = mDocsHelper.getRoot(StubProvider.ROOT_0_ID); 107 rootDir1 = mDocsHelper.getRoot(StubProvider.ROOT_1_ID); 108 } 109 110 @Override setUp()111 public void setUp() throws Exception { 112 device = UiDevice.getInstance(getInstrumentation()); 113 // NOTE: Must be the "target" context, else security checks in content provider will fail. 114 context = getInstrumentation().getTargetContext(); 115 userId = UserId.DEFAULT_USER; 116 automation = getInstrumentation().getUiAutomation(); 117 features = new Features.RuntimeFeatures(context.getResources(), null); 118 119 bots = new Bots(device, automation, context, TIMEOUT); 120 121 Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE); 122 123 mResolver = context.getContentResolver(); 124 mDocsHelper = new DocumentsProviderHelper(userId, getTestingProviderAuthority(), context, 125 getTestingProviderAuthority()); 126 127 device.setOrientationNatural(); 128 setupTestingRoots(); 129 130 launchActivity(); 131 resetStorage(); 132 133 // Since at the launch of activity, ROOT_0 and ROOT_1 have no files, drawer will 134 // automatically open for phone devices. Espresso register click() as (x, y) MotionEvents, 135 // so if a drawer is on top of a file we want to select, it will actually click the drawer. 136 // Thus to start a clean state, we always try to close first. 137 bots.roots.closeDrawer(); 138 139 // Configure the provider back to default. 140 mDocsHelper.configure(null, Bundle.EMPTY); 141 } 142 143 @Override tearDown()144 public void tearDown() throws Exception { 145 device.unfreezeRotation(); 146 mDocsHelper.cleanUp(); 147 super.tearDown(); 148 } 149 launchActivity()150 protected void launchActivity() { 151 final Intent intent = new Intent(context, FilesActivity.class); 152 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); 153 if (getInitialRoot() != null) { 154 intent.setAction(Intent.ACTION_VIEW); 155 intent.setDataAndType(getInitialRoot().getUri(), DocumentsContract.Root.MIME_TYPE_ITEM); 156 } 157 setActivityIntent(intent); 158 getActivity(); // Launch the activity. 159 } 160 resetStorage()161 protected void resetStorage() throws RemoteException { 162 mDocsHelper.clear(null, null); 163 device.waitForIdle(); 164 } 165 initTestFiles()166 protected void initTestFiles() throws RemoteException { 167 mDocsHelper.createFolder(rootDir0, dirName1); 168 mDocsHelper.createDocument(rootDir0, "text/plain", fileName1); 169 mDocsHelper.createDocument(rootDir0, "image/png", fileName2); 170 mDocsHelper.createDocumentWithFlags(rootDir0.documentId, "text/plain", fileNameNoRename, 171 Document.FLAG_SUPPORTS_WRITE); 172 173 mDocsHelper.createDocument(rootDir1, "text/plain", fileName3); 174 mDocsHelper.createDocument(rootDir1, "text/plain", fileName4); 175 } 176 assertDefaultContentOfTestDir0()177 void assertDefaultContentOfTestDir0() throws UiObjectNotFoundException { 178 bots.directory.waitForDocument(fileName1); 179 bots.directory.waitForDocument(fileName2); 180 bots.directory.waitForDocument(dirName1); 181 bots.directory.waitForDocument(fileNameNoRename); 182 bots.directory.assertDocumentsCount(4); 183 } 184 assertDefaultContentOfTestDir1()185 void assertDefaultContentOfTestDir1() throws UiObjectNotFoundException { 186 bots.directory.waitForDocument(fileName3); 187 bots.directory.waitForDocument(fileName4); 188 bots.directory.assertDocumentsCount(2); 189 } 190 191 /** 192 * Setup test Activity UI Mode YES or not(AUTO/YES/NO) before start to testing 193 * @param uiModeNight Constant for {@link #setNightMode(int)} 194 * 0 - MODE_NIGHT_AUTO 195 * 1 - MODE_NIGHT_NO 196 * 2 - MODE_NIGHT_YES 197 */ setSystemUiModeNight(int uiModeNight)198 protected void setSystemUiModeNight(int uiModeNight) { 199 int systemUiMode = getActivity().getResources().getConfiguration().uiMode 200 & Configuration.UI_MODE_NIGHT_MASK; 201 if(uiModeNight != systemUiMode) { 202 /* TODO since ag/4947691 enable config_lockDayNightMode to block app setNightMode() 203 create b/115315612 to handle the UiModeManager permission deny problem */ 204 mUiModeManager = (UiModeManager) getActivity() 205 .getSystemService(Context.UI_MODE_SERVICE); 206 mUiModeManager.setNightMode(uiModeNight); 207 device.waitForIdle(NIGHT_MODE_CHANGE_WAIT_TIME); 208 } 209 } 210 } 211