CTS tests for UiAutomator at API 17

Change-Id: Ibe1ef7c97b69ceee504e7aaceeb34e345170d6b1
diff --git a/tests/uiautomator/Android.mk b/tests/uiautomator/Android.mk
index b5bfae3..68b1dc2 100644
--- a/tests/uiautomator/Android.mk
+++ b/tests/uiautomator/Android.mk
@@ -22,7 +22,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_MODULE := CtsUiAutomatorTests
-LOCAL_JAVA_LIBRARIES := uiautomator_sdk_v16
+LOCAL_JAVA_LIBRARIES := uiautomator_sdk_v17
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_CTS_TEST_APK := CtsUiAutomatorApp
 LOCAL_CTS_TEST_APP_PACKAGE := com.android.cts.uiautomator
diff --git a/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java b/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java
index 1595e93..5de9805 100644
--- a/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java
+++ b/tests/uiautomator/src/com/android/cts/uiautomatortest/CtsUiAutomatorTest.java
@@ -16,6 +16,7 @@
 package com.android.cts.uiautomatortest;
 
 import android.graphics.Rect;
+import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.Log;
 
@@ -29,6 +30,7 @@
 import com.android.uiautomator.testrunner.UiAutomatorTestCase;
 
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.IOException;
 
 /**
@@ -37,7 +39,7 @@
 public class CtsUiAutomatorTest extends UiAutomatorTestCase {
     private static final String LOG_TAG = CtsUiAutomatorTest.class.getSimpleName();
     private static final String[] LIST_SCROLL_TESTS = new String[] {
-            "Test 17", "Test 11", "Test 30", "Test 29"
+            "Test 17", "Test 11", "Test 20"
     };
     private static final String LAUNCH_APP = "am start -a android.intent.action.MAIN"
             + " -n com.android.cts.uiautomator/.MainActivity -W";
@@ -46,6 +48,8 @@
     // Maximum wait for key object to become visible
     private static final int WAIT_EXIST_TIMEOUT = 5 * 1000;
 
+    private static final String SCREEN_SHOT_FILE_PATH_NAME = "/data/local/tmp/ctsScreenShot";
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -85,6 +89,13 @@
      * scroll is required to reach each item at each of the far ends.
      */
     public void testListScrollAndSelect() throws UiObjectNotFoundException {
+        UiScrollable listView = new UiScrollable(
+                new UiSelector().className(android.widget.ListView.class.getName()));
+
+        // on single fragment display
+        if (!listView.exists())
+            UiDevice.getInstance().pressBack();
+
         for (String test : LIST_SCROLL_TESTS) {
             openTest(test);
             verifyTestDetailsExists(test);
@@ -230,6 +241,7 @@
         assertFalse("Wait for exist must return false after press back", result.exists());
 
         // Home button test
+        openTest("Test 5");
         String pkgName = device.getCurrentPackageName();
         assertTrue("CTS test app must be running", pkgName.equals(PKG_NAME));
         device.pressHome();
@@ -363,6 +375,7 @@
      *
      * @throws UiObjectNotFoundException
      */
+    /*// broken in MR1
     public void testWebViewTextTraversal() throws UiObjectNotFoundException {
         openTest("Test 6");
         UiObject webView = new UiObject(new UiSelector().className(android.webkit.WebView.class
@@ -390,7 +403,7 @@
         device.pressDPadDown();
         text = device.getLastTraversedText();
         assertTrue("h4 text", text.contains("h4"));
-    }
+    }*/
 
     /**
      * Test when an object does not exist, an exception is thrown
@@ -608,6 +621,166 @@
     }
 
     /**
+     * Test Orientation APIs by causing rotations and verifying current state
+     *
+     * @throws RemoteException
+     * @throws UiObjectNotFoundException
+     * @since API Level 17
+     */
+    public void testRotation() throws RemoteException, UiObjectNotFoundException {
+        openTest("Test 5");
+        UiDevice device = UiDevice.getInstance();
+
+        device.setOrientationLeft();
+        device.waitForIdle(); // isNaturalOrientation is not waiting for idle
+        SystemClock.sleep(1000);
+        assertFalse("Device orientation should not be natural", device.isNaturalOrientation());
+
+        device.setOrientationNatural();
+        device.waitForIdle(); // isNaturalOrientation is not waiting for idle
+        SystemClock.sleep(1000);
+        assertTrue("Device orientation should be natural", device.isNaturalOrientation());
+
+        device.setOrientationRight();
+        device.waitForIdle(); // isNaturalOrientation is not waiting for idle
+        SystemClock.sleep(1000);
+        assertFalse("Device orientation should not be natural", device.isNaturalOrientation());
+
+        device.setOrientationNatural();
+    }
+
+    /**
+     * Reads the current device's product name. Since it is not possible to predetermine the
+     * would be value, the check verifies that the value is not null and not empty.
+     *
+     * @since API Level 17
+     */
+    public void testGetProductName() {
+        String name = UiDevice.getInstance().getProductName();
+        assertFalse("Product name check returned empty string", name.isEmpty());
+    }
+
+    /**
+     * Select each of the buttons by using only regex text
+     *
+     * @throws UiObjectNotFoundException
+     * @since API Level 17
+     */
+    public void testSelectByTextMatch() throws UiObjectNotFoundException {
+        openTest("Test 2");
+        getObjectByTextMatch(".*n\\s1$").click();
+        verifyDialogActionResults("Button 1");
+        getObjectByTextMatch(".*n\\s2$").click();
+        verifyDialogActionResults("Button 2");
+        getObjectByTextMatch(".*n\\s3$").click();
+        verifyDialogActionResults("Button 3");
+    }
+
+    /**
+     * Select each of the buttons by using only regex content-description
+     *
+     * @throws UiObjectNotFoundException
+     * @since API Level 17
+     */
+    public void testSelectByDescriptionMatch() throws UiObjectNotFoundException {
+        openTest("Test 2");
+        getObjectByDescriptionMatch(".*n\\s1$").click();
+        verifyDialogActionResults("Button 1");
+        getObjectByDescriptionMatch(".*n\\s2$").click();
+        verifyDialogActionResults("Button 2");
+        getObjectByDescriptionMatch(".*n\\s3$").click();
+        verifyDialogActionResults("Button 3");
+    }
+
+    /**
+     * Select each of the buttons by using only regex class name
+     *
+     * @throws UiObjectNotFoundException
+     * @since API Level 17
+     */
+    public void testSelectByClassMatch() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiObject tgl = getObjectByClassMatch(".*ToggleButton$", 0);
+        String tglValue = tgl.getText();
+        tgl.click();
+
+        assertFalse("Matching class by Regex failed", tglValue.equals(tgl.getText()));
+    }
+
+    /**
+     * Select each of the buttons by using only class type
+     *
+     * @throws UiObjectNotFoundException
+     * @since API Level 17
+     */
+    public void testSelectByClassType() throws UiObjectNotFoundException {
+        openTest("Test 5");
+        UiObject tgl = getObjectByClass(android.widget.ToggleButton.class, 0);
+        String tglValue = tgl.getText();
+        tgl.click();
+
+        assertFalse("Matching class by class type failed", tglValue.equals(tgl.getText()));
+    }
+
+    /**
+     * Test the coordinates of 3 buttons side by side verifying vertical and
+     * horizontal coordinates.
+     *
+     * @throws UiObjectNotFoundException
+     * @since API Level 17
+     */
+    public void testGetVisibleBounds() throws UiObjectNotFoundException {
+        openTest("Test 2");
+        Rect rect1 = getObjectByText("Button 1").getVisibleBounds();
+        Rect rect2 = getObjectByText("Button 2").getVisibleBounds();
+        Rect rect3 = getObjectByText("Button 3").getVisibleBounds();
+
+        assertTrue("X coordinate check failed",
+                rect1.left < rect2.left && rect2.right < rect3.right);
+        assertTrue("Y coordinate check failed",
+                rect1.top == rect2.top && rect2.bottom == rect3.bottom);
+    }
+
+   /**
+     * Tests the LongClick functionality in the API
+     *
+     * @throws UiObjectNotFoundException
+     * @since API Level 17
+     */
+    public void testSelectorLongClickable() throws UiObjectNotFoundException {
+        openTest("Test 2");
+        getObjectByText("Button 1").longClick();
+        verifyDialogActionResults("Longclick Button 1");
+    }
+
+    /**
+     * Test the UiSelector's long-clickable property
+     *
+     * @throws UiObjectNotFoundException
+     * @since API Level 17
+     */
+    public void testSelectorLongClickableProperty() throws UiObjectNotFoundException {
+        UiObject button3 = new UiObject(new UiSelector().className(
+                android.widget.Button.class).longClickable(true).instance(2));
+        button3.longClick();
+        verifyDialogActionResults("Longclick Button 3");
+    }
+
+    /**
+     * Takes a screen shot of the current display and checks if the file is
+     * created and is not zero size.
+     *
+     * @since API Level 17
+     */
+    public void testTakeScreenShots() {
+        File storePath = new File(SCREEN_SHOT_FILE_PATH_NAME);
+        getUiDevice().takeScreenshot(storePath);
+
+        assertTrue("Screenshot file not detected in store", storePath.exists());
+        assertTrue("Zero size for screenshot file", storePath.length() > 0);
+    }
+
+    /**
      * Private helper to open test views. Also covers UiScrollable tests
      *
      * @param name
@@ -636,10 +809,26 @@
         return new UiObject(new UiSelector().text(txt));
     }
 
+    private UiObject getObjectByTextMatch(String regex) {
+        return new UiObject(new UiSelector().textMatches(regex));
+    }
+
+    private UiObject getObjectByDescriptionMatch(String regex) {
+        return new UiObject(new UiSelector().descriptionMatches(regex));
+    }
+
     private UiObject getObjectByDescription(String txt) {
         return new UiObject(new UiSelector().description(txt));
     }
 
+    private UiObject getObjectByClassMatch(String regex, int instance) {
+        return new UiObject(new UiSelector().classNameMatches(regex).instance(instance));
+    }
+
+    private <T> UiObject getObjectByClass(Class<T> type, int instance) {
+        return new UiObject(new UiSelector().className(type).instance(instance));
+    }
+
     private UiObject getObjectByIndex(String className, int index) {
         return new UiObject(new UiSelector().className(className).index(index));
     }
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/strings.xml b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/strings.xml
index 73ab901..78b829f 100644
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/strings.xml
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/res/values/strings.xml
@@ -32,8 +32,11 @@
     <string name="test2_description_2">This tests a Button text changing dynamically after a click. The test should attempt to find the button after it has changed using its new text.</string>
     <string name="test3_description">The tests should read the clock, then write the clock back into the EditText then press submit. A dialog will display the time it took from reading the clock until submit is press. This can be used to get an idea of performance differences.</string>
     <string name="button1">Button 1</string>
+    <string name="button1long">Longclick Button 1</string>
     <string name="button2">Button 2</string>
+    <string name="button2long">Longclick Button 2</string>
     <string name="button3">Button 3</string>
+    <string name="button3long">Longclick Button 3</string>
     <string name="buttonBefore">Before</string>
     <string name="buttonAfter">After</string>
     <string name="dialog_title_result">Action results</string>
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test2DetailFragment.java b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test2DetailFragment.java
index cec98b5..4eade4b 100644
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test2DetailFragment.java
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/src/com/android/cts/uiautomator/Test2DetailFragment.java
@@ -78,6 +78,19 @@
             }
         });
 
+        mButton1.setOnLongClickListener(new Button.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                builder.setTitle(R.string.dialog_title_result);
+                builder.setPositiveButton(R.string.OK, null);
+                builder.setMessage(R.string.button1long);
+                AlertDialog diag = builder.create();
+                diag.show();
+                return true;
+            }
+        });
+
         mButton2.setOnClickListener(new Button.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -90,6 +103,19 @@
             }
         });
 
+        mButton2.setOnLongClickListener(new Button.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                builder.setTitle(R.string.dialog_title_result);
+                builder.setPositiveButton(R.string.OK, null);
+                builder.setMessage(R.string.button2long);
+                AlertDialog diag = builder.create();
+                diag.show();
+                return true;
+            }
+        });
+
         mButton3.setOnClickListener(new Button.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -102,6 +128,19 @@
             }
         });
 
+        mButton3.setOnLongClickListener(new Button.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                builder.setTitle(R.string.dialog_title_result);
+                builder.setPositiveButton(R.string.OK, null);
+                builder.setMessage(R.string.button3long);
+                AlertDialog diag = builder.create();
+                diag.show();
+                return true;
+            }
+        });
+
         mDynaButton.setOnClickListener(new Button.OnClickListener() {
             @Override
             public void onClick(View v) {