summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2016-05-19 12:15:39 -0700
committerSunny Goyal <sunnygoyal@google.com>2016-05-26 17:20:22 -0700
commit6d02c7a0337d37e5b1c596a4acec0c292a9b7f93 (patch)
tree7018e3fcfa48ff3cd04e559cd86b57ab04ffcee0 /tests
parent5c93eac3ae163a5a3d866db24d9b853caa9b9f88 (diff)
downloadandroid_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')
-rw-r--r--tests/src/com/android/launcher3/BindWidgetTest.java101
-rw-r--r--tests/src/com/android/launcher3/QuickAddWidgetTest.java88
-rw-r--r--tests/src/com/android/launcher3/ui/AddWidgetTest.java64
-rw-r--r--tests/src/com/android/launcher3/ui/AllAppsAppLaunchTest.java52
-rw-r--r--tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java57
-rw-r--r--tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java266
-rw-r--r--tests/src/com/android/launcher3/ui/RotationPreferenceTest.java (renamed from tests/src/com/android/launcher3/RotationPreferenceTest.java)27
-rw-r--r--tests/src/com/android/launcher3/util/Condition.java54
-rw-r--r--tests/src/com/android/launcher3/util/Wait.java30
9 files changed, 535 insertions, 204 deletions
diff --git a/tests/src/com/android/launcher3/BindWidgetTest.java b/tests/src/com/android/launcher3/BindWidgetTest.java
index 34b117430..81cb8b56b 100644
--- a/tests/src/com/android/launcher3/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/BindWidgetTest.java
@@ -1,38 +1,30 @@
package com.android.launcher3;
import android.annotation.TargetApi;
-import android.app.SearchManager;
import android.appwidget.AppWidgetHost;
-import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
-import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiSelector;
-import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
+import com.android.launcher3.ui.LauncherInstrumentationTestCase;
import com.android.launcher3.util.ManagedProfileHeuristic;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetHostViewLoader;
-import java.io.FileInputStream;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
/**
* Tests for bind widget flow.
@@ -41,12 +33,8 @@ import java.util.concurrent.atomic.AtomicReference;
*/
@LargeTest
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
-public class BindWidgetTest extends InstrumentationTestCase {
+public class BindWidgetTest extends LauncherInstrumentationTestCase {
- private static final long DEFAULT_TIMEOUT = 6000;
-
- private UiDevice mDevice;
- private Context mTargetContext;
private ContentResolver mResolver;
private AppWidgetManagerCompat mWidgetManager;
@@ -59,23 +47,9 @@ public class BindWidgetTest extends InstrumentationTestCase {
protected void setUp() throws Exception {
super.setUp();
- mDevice = UiDevice.getInstance(getInstrumentation());
- mTargetContext = getInstrumentation().getTargetContext();
mResolver = mTargetContext.getContentResolver();
mWidgetManager = AppWidgetManagerCompat.getInstance(mTargetContext);
-
- // Check bind widget permission
- String pkg = mTargetContext.getPackageName();
- if (mTargetContext.getPackageManager().checkPermission(
- pkg, android.Manifest.permission.BIND_APPWIDGET)
- != PackageManager.PERMISSION_GRANTED) {
- ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation().executeShellCommand(
- "appwidget grantbind --package " + pkg);
- // Read the input stream fully.
- FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
- while (fis.read() != -1);
- fis.close();
- }
+ grantWidgetPermission();
// Clear all existing data
LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
@@ -264,61 +238,14 @@ public class BindWidgetTest extends InstrumentationTestCase {
throw new IllegalArgumentException(t);
}
// Launch the home activity
- getInstrumentation().getContext().startActivity(new Intent(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_HOME)
- .setPackage(mTargetContext.getPackageName())
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
-
+ startLauncher();
// Verify UI
UiSelector selector = new UiSelector().packageName(mTargetContext.getPackageName())
.className(widgetClass);
if (desc != null) {
selector = selector.description(desc);
}
- assertTrue(mDevice.findObject(selector).waitForExists(DEFAULT_TIMEOUT));
- }
-
- /**
- * Finds a widget provider which can fit on the home screen.
- * @param hasConfigureScreen if true, a provider with a config screen is returned.
- */
- private 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;
+ assertTrue(mDevice.findObject(selector).waitForExists(DEFAULT_UI_TIMEOUT));
}
/**
@@ -398,24 +325,6 @@ public class BindWidgetTest extends InstrumentationTestCase {
}
/**
- * Runs the callback on the UI thread and returns the result.
- */
- private <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();
- }
-
- /**
* Blocks the current thread until all the jobs in the main worker thread are complete.
*/
private void waitUntilLoaderIdle() throws InterruptedException {
diff --git a/tests/src/com/android/launcher3/QuickAddWidgetTest.java b/tests/src/com/android/launcher3/QuickAddWidgetTest.java
deleted file mode 100644
index 007829435..000000000
--- a/tests/src/com/android/launcher3/QuickAddWidgetTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.android.launcher3;
-
-import android.content.Intent;
-import android.graphics.Point;
-import android.os.SystemClock;
-import android.support.test.uiautomator.By;
-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.test.suitebuilder.annotation.LargeTest;
-import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-
-import java.util.List;
-
-/**
- * Add an arbitrary widget from the widget picker very quickly to test potential race conditions.
- */
-@LargeTest
-public class QuickAddWidgetTest extends InstrumentationTestCase {
- // Disabled because it's flaky and not particularly useful. But this class could still be useful
- // as an example if we want other UI tests in the future.
- private static final boolean DISABLED = true;
-
- private UiDevice mDevice;
- private String mTargetPackage;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mDevice = UiDevice.getInstance(getInstrumentation());
-
- // Set Launcher3 as home.
- mTargetPackage = getInstrumentation().getTargetContext().getPackageName();
- Intent homeIntent = new Intent(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_HOME)
- .setPackage(mTargetPackage)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- getInstrumentation().getContext().startActivity(homeIntent);
- mDevice.wait(Until.hasObject(By.pkg(mTargetPackage).depth(0)), 3000);
- }
-
- public void testAddWidgetQuickly() throws Exception {
- if (DISABLED) return;
- mDevice.pressMenu(); // Enter overview mode.
- mDevice.wait(Until.findObject(By.text("Widgets")), 3000).click();
- UiObject2 calendarWidget = getWidgetByName("Clock");
- Point center = calendarWidget.getVisibleCenter();
- // Touch widget just long enough to pick it up (longPressTimeout), then let go immediately.
- getInstrumentation().sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
- SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, center.x, center.y, 0));
- Thread.sleep(ViewConfiguration.getLongPressTimeout() + 50);
- getInstrumentation().sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),
- SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, center.x, center.y, 0));
-
- assertTrue("Drag was never started", isOnHomescreen());
- }
-
- private UiObject2 getWidgetByName(String name) {
- UiObject2 widgetsList = mDevice.wait(Until.findObject(By.res(mTargetPackage,
- "widgets_list_view")), 3000);
- do {
- UiObject2 widget = getVisibleWidgetByName(name);
- if (widget != null) {
- return widget;
- }
- } while (widgetsList.scroll(Direction.DOWN, 1f));
- return getVisibleWidgetByName(name);
- }
-
- private UiObject2 getVisibleWidgetByName(String name) {
- List<UiObject2> visibleWidgets = mDevice.wait(Until.findObjects(By.clazz(
- "android.widget.LinearLayout")), 3000);
- for (UiObject2 widget : visibleWidgets) {
- if (widget.hasObject(By.text(name))) {
- return widget;
- }
- }
- return null;
- }
-
- private boolean isOnHomescreen() {
- return mDevice.wait(Until.hasObject(By.res(mTargetPackage, "hotseat")), 3000);
- }
-}
diff --git a/tests/src/com/android/launcher3/ui/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/AddWidgetTest.java
new file mode 100644
index 000000000..95d9289dd
--- /dev/null
+++ b/tests/src/com/android/launcher3/ui/AddWidgetTest.java
@@ -0,0 +1,64 @@
+package com.android.launcher3.ui;
+
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiObject2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.View;
+
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppWidgetInfo;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.Workspace.ItemOperator;
+import com.android.launcher3.util.Condition;
+import com.android.launcher3.util.Wait;
+import com.android.launcher3.widget.WidgetCell;
+
+/**
+ * Test to add widget from widget tray
+ */
+@LargeTest
+public class AddWidgetTest extends LauncherInstrumentationTestCase {
+
+ private LauncherAppWidgetProviderInfo widgetInfo;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ widgetInfo = findWidgetProvider(false /* hasConfigureScreen */);
+ }
+
+ public void testDragIcon_portrait() throws Throwable {
+ lockRotation(true);
+ performTest();
+ }
+
+ public void testDragIcon_landscape() throws Throwable {
+ lockRotation(false);
+ performTest();
+ }
+
+ private void performTest() throws Throwable {
+ clearHomescreen();
+ Launcher launcher = startLauncher();
+
+ // Open all apps and wait for load complete.
+ final UiObject2 widgetContainer = openWidgetsTray();
+ assertTrue(Wait.atMost(Condition.minChildCount(widgetContainer, 2), DEFAULT_UI_TIMEOUT));
+
+ // Drag widget to homescreen
+ UiObject2 widget = scrollAndFind(widgetContainer, By.clazz(WidgetCell.class)
+ .hasDescendant(By.text(widgetInfo.getLabel(mTargetContext.getPackageManager()))));
+ dragToWorkspace(widget);
+
+ assertNotNull(launcher.getWorkspace().getFirstMatch(new ItemOperator() {
+ @Override
+ public boolean evaluate(ItemInfo info, View view) {
+ return info instanceof LauncherAppWidgetInfo &&
+ ((LauncherAppWidgetInfo) info).providerName.equals(widgetInfo.provider);
+ }
+ }));
+ }
+}
diff --git a/tests/src/com/android/launcher3/ui/AllAppsAppLaunchTest.java b/tests/src/com/android/launcher3/ui/AllAppsAppLaunchTest.java
new file mode 100644
index 000000000..abe6b9591
--- /dev/null
+++ b/tests/src/com/android/launcher3/ui/AllAppsAppLaunchTest.java
@@ -0,0 +1,52 @@
+package com.android.launcher3.ui;
+
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.launcher3.compat.LauncherActivityInfoCompat;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.util.Condition;
+import com.android.launcher3.util.Wait;
+
+/**
+ * Test for verifying apps is launched from all-apps
+ */
+@LargeTest
+public class AllAppsAppLaunchTest extends LauncherInstrumentationTestCase {
+
+ private LauncherActivityInfoCompat mSettingsApp;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext)
+ .getActivityList("com.android.settings", UserHandleCompat.myUserHandle()).get(0);
+ }
+
+ public void testAppLauncher_portrait() throws Exception {
+ lockRotation(true);
+ performTest();
+ }
+
+ public void testAppLauncher_landscape() throws Exception {
+ lockRotation(false);
+ performTest();
+ }
+
+ private void performTest() throws Exception {
+ startLauncher();
+
+ // Open all apps and wait for load complete
+ final UiObject2 appsContainer = openAllApps();
+ assertTrue(Wait.atMost(Condition.minChildCount(appsContainer, 2), DEFAULT_UI_TIMEOUT));
+
+ // Open settings app and verify app launched
+ scrollAndFind(appsContainer, By.text(mSettingsApp.getLabel().toString())).click();
+ assertTrue(mDevice.wait(Until.hasObject(By.pkg(
+ mSettingsApp.getComponentName().getPackageName()).depth(0)), DEFAULT_UI_TIMEOUT));
+ }
+}
diff --git a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
new file mode 100644
index 000000000..56fc90ab1
--- /dev/null
+++ b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
@@ -0,0 +1,57 @@
+package com.android.launcher3.ui;
+
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.android.launcher3.compat.LauncherActivityInfoCompat;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.util.Condition;
+import com.android.launcher3.util.Wait;
+
+/**
+ * Test for dragging an icon from all-apps to homescreen.
+ */
+@LargeTest
+public class AllAppsIconToHomeTest extends LauncherInstrumentationTestCase {
+
+ private LauncherActivityInfoCompat mSettingsApp;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext)
+ .getActivityList("com.android.settings", UserHandleCompat.myUserHandle()).get(0);
+ }
+
+ public void testDragIcon_portrait() throws Throwable {
+ lockRotation(true);
+ performTest();
+ }
+
+ public void testDragIcon_landscape() throws Throwable {
+ lockRotation(false);
+ performTest();
+ }
+
+ private void performTest() throws Throwable {
+ clearHomescreen();
+ startLauncher();
+
+ // Open all apps and wait for load complete.
+ final UiObject2 appsContainer = openAllApps();
+ assertTrue(Wait.atMost(Condition.minChildCount(appsContainer, 2), DEFAULT_UI_TIMEOUT));
+
+ // Drag icon to homescreen.
+ UiObject2 icon = scrollAndFind(appsContainer, By.text(mSettingsApp.getLabel().toString()));
+ dragToWorkspace(icon);
+
+ // Verify that the icon works on homescreen.
+ mDevice.findObject(By.text(mSettingsApp.getLabel().toString())).click();
+ assertTrue(mDevice.wait(Until.hasObject(By.pkg(
+ mSettingsApp.getComponentName().getPackageName()).depth(0)), DEFAULT_UI_TIMEOUT));
+ }
+}
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);
+ }
+}
diff --git a/tests/src/com/android/launcher3/RotationPreferenceTest.java b/tests/src/com/android/launcher3/ui/RotationPreferenceTest.java
index 7259d35c2..e84ad047f 100644
--- a/tests/src/com/android/launcher3/RotationPreferenceTest.java
+++ b/tests/src/com/android/launcher3/ui/RotationPreferenceTest.java
@@ -1,24 +1,20 @@
-package com.android.launcher3;
+package com.android.launcher3.ui;
-import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Rect;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector;
-import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
/**
* Test for auto rotate preference.
*/
@MediumTest
-public class RotationPreferenceTest extends InstrumentationTestCase {
-
- private UiDevice mDevice;
- private Context mTargetContext;
- private String mTargetPackage;
+public class RotationPreferenceTest extends LauncherInstrumentationTestCase {
private SharedPreferences mPrefs;
private boolean mOriginalRotationValue;
@@ -48,7 +44,7 @@ public class RotationPreferenceTest extends InstrumentationTestCase {
setRotationEnabled(false);
mDevice.setOrientationRight();
- goToLauncher();
+ startLauncher();
Rect hotseat = getHotseatBounds();
assertTrue(hotseat.width() > hotseat.height());
@@ -62,21 +58,12 @@ public class RotationPreferenceTest extends InstrumentationTestCase {
setRotationEnabled(true);
mDevice.setOrientationRight();
- goToLauncher();
+ startLauncher();
Rect hotseat = getHotseatBounds();
assertTrue(hotseat.width() < hotseat.height());
}
- private void goToLauncher() {
- Intent homeIntent = new Intent(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_HOME)
- .setPackage(mTargetPackage)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- getInstrumentation().getContext().startActivity(homeIntent);
- mDevice.findObject(new UiSelector().packageName(mTargetPackage)).waitForExists(6000);
- }
-
private void setRotationEnabled(boolean enabled) {
mPrefs.edit().putBoolean(Utilities.ALLOW_ROTATION_PREFERENCE_KEY, enabled).commit();
}
diff --git a/tests/src/com/android/launcher3/util/Condition.java b/tests/src/com/android/launcher3/util/Condition.java
new file mode 100644
index 000000000..e9ee67cdb
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/Condition.java
@@ -0,0 +1,54 @@
+package com.android.launcher3.util;
+
+import android.support.test.uiautomator.UiObject2;
+
+import com.android.launcher3.MainThreadExecutor;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public abstract class Condition {
+
+ public abstract boolean isTrue() throws Throwable;
+
+ /**
+ * Converts the condition to be run on UI thread.
+ */
+ public static Condition runOnUiThread(final Condition condition) {
+ final MainThreadExecutor executor = new MainThreadExecutor();
+ return new Condition() {
+ @Override
+ public boolean isTrue() throws Throwable {
+ final AtomicBoolean value = new AtomicBoolean(false);
+ final Throwable[] exceptions = new Throwable[1];
+ final CountDownLatch latch = new CountDownLatch(1);
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ value.set(condition.isTrue());
+ } catch (Throwable e) {
+ exceptions[0] = e;
+ }
+
+ }
+ });
+ latch.await(1, TimeUnit.SECONDS);
+ if (exceptions[0] != null) {
+ throw exceptions[0];
+ }
+ return value.get();
+ }
+ };
+ }
+
+ public static Condition minChildCount(final UiObject2 obj, final int childCount) {
+ return new Condition() {
+ @Override
+ public boolean isTrue() {
+ return obj.getChildCount() >= childCount;
+ }
+ };
+ }
+}
diff --git a/tests/src/com/android/launcher3/util/Wait.java b/tests/src/com/android/launcher3/util/Wait.java
new file mode 100644
index 000000000..02a19137e
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/Wait.java
@@ -0,0 +1,30 @@
+package com.android.launcher3.util;
+
+import android.os.SystemClock;
+
+/**
+ * A utility class for waiting for a condition to be true.
+ */
+public class Wait {
+
+ private static final long DEFAULT_SLEEP_MS = 200;
+
+ public static boolean atMost(Condition condition, long timeout) {
+ return atMost(condition, timeout, DEFAULT_SLEEP_MS);
+ }
+
+ public static boolean atMost(Condition condition, long timeout, long sleepMillis) {
+ long endTime = SystemClock.uptimeMillis() + timeout;
+ while (SystemClock.uptimeMillis() < endTime) {
+ try {
+ if (condition.isTrue()) {
+ return true;
+ }
+ } catch (Throwable t) {
+ // Ignore
+ }
+ SystemClock.sleep(sleepMillis);
+ }
+ return false;
+ }
+}