diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2016-05-19 12:15:39 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2016-05-26 17:20:22 -0700 |
commit | 6d02c7a0337d37e5b1c596a4acec0c292a9b7f93 (patch) | |
tree | 7018e3fcfa48ff3cd04e559cd86b57ab04ffcee0 /tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java | |
parent | 5c93eac3ae163a5a3d866db24d9b853caa9b9f88 (diff) | |
download | android_packages_apps_Trebuchet-6d02c7a0337d37e5b1c596a4acec0c292a9b7f93.tar.gz android_packages_apps_Trebuchet-6d02c7a0337d37e5b1c596a4acec0c292a9b7f93.tar.bz2 android_packages_apps_Trebuchet-6d02c7a0337d37e5b1c596a4acec0c292a9b7f93.zip |
Adding some UI tests
> Launcher app from all-apps
> Drag icon to all-apps and launch it
> Add widget from widget tray
Change-Id: I6bd6128a7b560a23a887d1fb40bfcda25b9b02e7
Diffstat (limited to 'tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java')
-rw-r--r-- | tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java b/tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java new file mode 100644 index 000000000..a59f0ffc9 --- /dev/null +++ b/tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java @@ -0,0 +1,266 @@ +package com.android.launcher3.ui; + +import android.app.SearchManager; +import android.appwidget.AppWidgetProviderInfo; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Point; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.os.SystemClock; +import android.support.test.uiautomator.By; +import android.support.test.uiautomator.BySelector; +import android.support.test.uiautomator.Direction; +import android.support.test.uiautomator.UiDevice; +import android.support.test.uiautomator.UiObject2; +import android.support.test.uiautomator.Until; +import android.test.InstrumentationTestCase; +import android.view.MotionEvent; + +import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherAppWidgetProviderInfo; +import com.android.launcher3.LauncherClings; +import com.android.launcher3.LauncherSettings; +import com.android.launcher3.R; +import com.android.launcher3.Utilities; +import com.android.launcher3.compat.AppWidgetManagerCompat; +import com.android.launcher3.util.ManagedProfileHeuristic; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Locale; +import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Base class for all instrumentation tests providing various utility methods. + */ +public class LauncherInstrumentationTestCase extends InstrumentationTestCase { + + public static final long DEFAULT_UI_TIMEOUT = 3000; + + protected UiDevice mDevice; + protected Context mTargetContext; + protected String mTargetPackage; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mDevice = UiDevice.getInstance(getInstrumentation()); + mTargetContext = getInstrumentation().getTargetContext(); + mTargetPackage = mTargetContext.getPackageName(); + } + + protected void lockRotation(boolean naturalOrientation) throws RemoteException { + Utilities.getPrefs(mTargetContext) + .edit() + .putBoolean(Utilities.ALLOW_ROTATION_PREFERENCE_KEY, !naturalOrientation) + .commit(); + + if (naturalOrientation) { + mDevice.setOrientationNatural(); + } else { + mDevice.setOrientationRight(); + } + } + + /** + * Starts the launcher activity in the target package and returns the Launcher instance. + */ + protected Launcher startLauncher() { + Intent homeIntent = new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_HOME) + .setPackage(mTargetPackage) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return (Launcher) getInstrumentation().startActivitySync(homeIntent); + } + + /** + * Grants the launcher permission to bind widgets. + */ + protected void grantWidgetPermission() throws IOException { + // Check bind widget permission + if (mTargetContext.getPackageManager().checkPermission( + mTargetPackage, android.Manifest.permission.BIND_APPWIDGET) + != PackageManager.PERMISSION_GRANTED) { + ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation().executeShellCommand( + "appwidget grantbind --package " + mTargetPackage); + // Read the input stream fully. + FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); + while (fis.read() != -1); + fis.close(); + } + } + + /** + * Opens all apps and returns the recycler view + */ + protected UiObject2 openAllApps() { + mDevice.wait(Until.findObject( + By.desc(mTargetContext.getString(R.string.all_apps_button_label))), DEFAULT_UI_TIMEOUT).click(); + return findViewById(R.id.apps_list_view); + } + + /** + * Opens widget tray and returns the recycler view. + */ + protected UiObject2 openWidgetsTray() { + mDevice.pressMenu(); // Enter overview mode. + mDevice.wait(Until.findObject( + By.text(mTargetContext.getString(R.string.widget_button_text) + .toUpperCase(Locale.getDefault()))), DEFAULT_UI_TIMEOUT).click(); + return findViewById(R.id.widgets_list_view); + } + + /** + * Scrolls the {@param container} until it finds an object matching {@param condition}. + * @return the matching object. + */ + protected UiObject2 scrollAndFind(UiObject2 container, BySelector condition) { + do { + UiObject2 widget = container.findObject(condition); + if (widget != null) { + return widget; + } + } while (container.scroll(Direction.DOWN, 1f)); + return container.findObject(condition); + } + + /** + * Drags an icon to the center of homescreen. + */ + protected void dragToWorkspace(UiObject2 icon) { + Point center = icon.getVisibleCenter(); + + // Action Down + sendPointer(MotionEvent.ACTION_DOWN, center); + + // Wait until "Remove/Delete target is visible + assertNotNull(findViewById(R.id.delete_target_text)); + + Point moveLocation = findViewById(R.id.drag_layer).getVisibleCenter(); + + // Move to center + while(!moveLocation.equals(center)) { + center.x = getNextMoveValue(moveLocation.x, center.x); + center.y = getNextMoveValue(moveLocation.y, center.y); + sendPointer(MotionEvent.ACTION_MOVE, center); + } + sendPointer(MotionEvent.ACTION_UP, center); + + // Wait until remove target is gone. + mDevice.wait(Until.gone(getSelectorForId(R.id.delete_target_text)), DEFAULT_UI_TIMEOUT); + } + + private int getNextMoveValue(int targetValue, int oldValue) { + if (targetValue - oldValue > 10) { + return oldValue + 10; + } else if (targetValue - oldValue < -10) { + return oldValue - 10; + } else { + return targetValue; + } + } + + private void sendPointer(int action, Point point) { + MotionEvent event = MotionEvent.obtain(SystemClock.uptimeMillis(), + SystemClock.uptimeMillis(), action, point.x, point.y, 0); + getInstrumentation().sendPointerSync(event); + event.recycle(); + } + + /** + * Removes all icons from homescreen and hotseat. + */ + public void clearHomescreen() throws Throwable { + LauncherSettings.Settings.call(mTargetContext.getContentResolver(), + LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB); + LauncherSettings.Settings.call(mTargetContext.getContentResolver(), + LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG); + LauncherClings.markFirstRunClingDismissed(mTargetContext); + ManagedProfileHeuristic.markExistingUsersForNoFolderCreation(mTargetContext); + + runTestOnUiThread(new Runnable() { + @Override + public void run() { + // Reset the loader state + LauncherAppState.getInstance().getModel().resetLoadedState(true, true); + } + }); + } + + /** + * Runs the callback on the UI thread and returns the result. + */ + protected <T> T getOnUiThread(final Callable<T> callback) { + final AtomicReference<T> result = new AtomicReference<>(null); + try { + runTestOnUiThread(new Runnable() { + @Override + public void run() { + try { + result.set(callback.call()); + } catch (Exception e) { } + } + }); + } catch (Throwable t) { } + return result.get(); + } + + /** + * Finds a widget provider which can fit on the home screen. + * @param hasConfigureScreen if true, a provider with a config screen is returned. + */ + protected LauncherAppWidgetProviderInfo findWidgetProvider(final boolean hasConfigureScreen) { + LauncherAppWidgetProviderInfo info = getOnUiThread(new Callable<LauncherAppWidgetProviderInfo>() { + @Override + public LauncherAppWidgetProviderInfo call() throws Exception { + InvariantDeviceProfile idv = + LauncherAppState.getInstance().getInvariantDeviceProfile(); + + ComponentName searchComponent = ((SearchManager) mTargetContext + .getSystemService(Context.SEARCH_SERVICE)).getGlobalSearchActivity(); + String searchPackage = searchComponent == null + ? null : searchComponent.getPackageName(); + + for (AppWidgetProviderInfo info : + AppWidgetManagerCompat.getInstance(mTargetContext).getAllProviders()) { + if ((info.configure != null) ^ hasConfigureScreen) { + continue; + } + // Exclude the widgets in search package, as Launcher already binds them in + // QSB, so they can cause conflicts. + if (info.provider.getPackageName().equals(searchPackage)) { + continue; + } + LauncherAppWidgetProviderInfo widgetInfo = LauncherAppWidgetProviderInfo + .fromProviderInfo(mTargetContext, info); + if (widgetInfo.minSpanX >= idv.numColumns + || widgetInfo.minSpanY >= idv.numRows) { + continue; + } + return widgetInfo; + } + return null; + } + }); + if (info == null) { + throw new IllegalArgumentException("No valid widget provider"); + } + return info; + } + + protected UiObject2 findViewById(int id) { + return mDevice.wait(Until.findObject(getSelectorForId(id)), DEFAULT_UI_TIMEOUT); + } + + protected BySelector getSelectorForId(int id) { + String name = mTargetContext.getResources().getResourceEntryName(id); + return By.res(mTargetPackage, name); + } +} |