blob: 65e7b9dba863ae3a98f89601760178749b65419b [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.uiautomator.tests.cts;
import android.content.Intent;
import android.content.ComponentName;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import com.android.uiautomator.core.UiCollection;
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.core.UiWatcher;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import java.io.File;
import java.io.IOException;
/**
* Sanity test uiautomator functionality on target device.
*/
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 20", "Test 35"
};
private static final String PKG_NAME = "com.android.uiautomator.tests.cts.testapp";
// 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 = "ctsScreenShot";
@Override
protected void setUp() throws Exception {
super.setUp();
// Make sure the test app is always running
UiDevice.getInstance().waitForIdle();
if (!new UiObject(new UiSelector().packageName(PKG_NAME)).exists()) {
Intent intent = new Intent(Intent.ACTION_MAIN)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.setComponent(new ComponentName(PKG_NAME, PKG_NAME + ".MainActivity"));
getInstrumentation().getContext().startActivity(intent);
}
}
/*
* Items in the listScrollTests array should be spread out such that a
* 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);
}
}
/**
* Test erasing of multi word text in edit field and input of new text. Test
* verifying input text using a complex UiSelector
*
* @throws UiObjectNotFoundException
*/
public void testTextEraseAndInput() throws UiObjectNotFoundException {
String testText = "Android Ui Automator Input Text";
openTest("Test 1");
UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
.getName()));
editText.setText(testText);
UiObject submitButton = new UiObject(new UiSelector()
.className(android.widget.Button.class.getName()).clickable(true)
.textStartsWith("Submit"));
submitButton.click();
UiObject result = new UiObject(new UiSelector().className(
android.widget.LinearLayout.class.getName()).childSelector(
(new UiSelector().className(android.widget.ScrollView.class.getName())
.childSelector(new UiSelector().className(android.widget.TextView.class
.getName())))));
if (!testText.equals(result.getText())) {
throw new UiObjectNotFoundException("Test text: " + testText);
}
getObjectByText("OK").click();
}
/**
* Select each of the buttons by using only the content description property
*
* @throws UiObjectNotFoundException
*/
public void testSelectByContentDescription() throws UiObjectNotFoundException {
openTest("Test 2");
getObjectByDescription("Button 1").click();
verifyDialogActionResults("Button 1");
getObjectByDescription("Button 2").click();
verifyDialogActionResults("Button 2");
getObjectByDescription("Button 3").click();
verifyDialogActionResults("Button 3");
}
/**
* Select each of the buttons by using only the text property
*
* @throws UiObjectNotFoundException
*/
public void testSelectByText() throws UiObjectNotFoundException {
openTest("Test 2");
getObjectByText("Button 1").click();
verifyDialogActionResults("Button 1");
getObjectByText("Button 2").click();
verifyDialogActionResults("Button 2");
getObjectByText("Button 3").click();
verifyDialogActionResults("Button 3");
}
/**
* Select each of the buttons by using only the index property
*
* @throws UiObjectNotFoundException
*/
public void testSelectByIndex() throws UiObjectNotFoundException {
openTest("Test 2");
getObjectByIndex(android.widget.Button.class.getName(), 0).click();
verifyDialogActionResults("Button 1");
getObjectByIndex(android.widget.Button.class.getName(), 1).click();
verifyDialogActionResults("Button 2");
getObjectByIndex(android.widget.Button.class.getName(), 2).click();
verifyDialogActionResults("Button 3");
}
/**
* Select each of the buttons by using only the instance number
*
* @throws UiObjectNotFoundException
*/
public void testSelectByInstance() throws UiObjectNotFoundException {
openTest("Test 2");
getObjectByInstance(android.widget.Button.class.getName(), 0).click();
verifyDialogActionResults("Button 1");
getObjectByInstance(android.widget.Button.class.getName(), 1).click();
verifyDialogActionResults("Button 2");
getObjectByInstance(android.widget.Button.class.getName(), 2).click();
verifyDialogActionResults("Button 3");
}
/**
* Test when a node's state is changed due to an action, it is updated in the accessibility
* hierarchy.
*
* @throws UiObjectNotFoundException
*/
public void testSelectAfterContentChanged() throws UiObjectNotFoundException {
openTest("Test 2");
UiObject dynaButton = getObjectByText("Before");
dynaButton.click();
assertTrue("Button state change is not refreshed in accessibility hierarchy",
getObjectByText("After").exists());
}
/**
* Test opening the options menu using the soft buttons
*
* @throws UiObjectNotFoundException
* @throws InterruptedException
* @throws IOException
*/
public void testDeviceSoftKeys() throws UiObjectNotFoundException, IOException,
InterruptedException {
openTest("Test 2");
UiDevice device = UiDevice.getInstance();
device.pressMenu();
getObjectByText("Finish").click();
verifyDialogActionResults("Finish");
// Back button
openTest("Test 1");
UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
.getName()));
editText.setText("Android Geppetto Test Application");
UiObject submitButton = new UiObject(new UiSelector()
.className(android.widget.Button.class.getName()).clickable(true)
.textStartsWith("Submit"));
submitButton.click();
// Text from the popup dialog
UiObject result = new UiObject(new UiSelector().textContains("geppetto"));
// Back button test to dismiss the dialog
assertTrue("Wait for exist must return true", result.waitForExists(2000));
device.pressBack();
result.waitUntilGone(1000);
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();
boolean gone = new UiObject(new UiSelector().packageName(PKG_NAME)).waitUntilGone(5000);
assertTrue("CTS test app still visble after pressing home", gone);
}
/**
* This view is in constant update generating window content changed events.
* The test will read the time displayed and exhaust each wait for idle
* timeout until it read and sets the text back into the edit field and
* presses submit. A dialog box should pop up with the time it took since
* reading the value until pressing submit.
*
* @throws UiObjectNotFoundException
*/
public void testWaitForIdleTimeout() throws UiObjectNotFoundException {
openTest("Test 3");
UiObject clk = new UiObject(new UiSelector().descriptionStartsWith("Performance "));
// First default wait for idle timeout assumed to be 10 seconds
String txtTime = clk.getText();
UiObject edit = new UiObject(new UiSelector().className(android.widget.EditText.class
.getName()));
// Second default wait for idle timeout assumed to be 10 seconds.
// Total ~20.
edit.setText(txtTime);
// Third default wait for idle timeout assumed to be 10 seconds.
// Total ~30.
getObjectByText("Submit").click();
// The value read should have value between 30 and 60 seconds indicating
// that the internal default timeouts for wait-for-idle is in acceptable
// range.
UiObject readTime = new UiObject(new UiSelector().className(
android.widget.TextView.class.getName()).instance(1));
String timeDiff = readTime.getText();
Log.i(LOG_TAG, "Sync time: " + timeDiff);
getObjectByText("OK").click();
int totalDelay = Integer.parseInt(timeDiff);
// Cumulative waits in this test should add up to at minimum 30 seconds
assertFalse("Timeout for wait-for-idle is too short. Expecting minimum 30 seconds",
totalDelay < 30 * 1000);
// allow for tolerance in time measurements due to differences between
// device speeds
assertFalse("Timeout for wait-for-idle is too long. Expecting maximum 60 seconds",
totalDelay > 60 * 1000);
}
/**
* This view is in constant update generating window content changed events.
* This test uses the soft key presses and clicks while the background
* screen is constantly updating causing a constant busy state.
*
* @throws UiObjectNotFoundException
*/
public void testVerifyMenuClicks() throws UiObjectNotFoundException {
openTest("Test 3");
UiDevice.getInstance().pressMenu();
new UiObject(new UiSelector().text("Submit")).click();
verifyDialogActionResults("Submit");
UiDevice.getInstance().pressMenu();
new UiObject(new UiSelector().text("Exit")).click();
verifyDialogActionResults("Exit");
}
/**
* Verifies swipeRight, swipeLeft and raw swipe APIs perform as expected.
*
* @throws UiObjectNotFoundException
*/
public void testSwipes() throws UiObjectNotFoundException {
openTest("Test 4");
UiObject textView = new UiObject(new UiSelector().textContains("["));
textView.swipeLeft(10);
assertTrue("UiObject swipe left 1->2", "[ 2 ]".equals(textView.getText()));
textView.swipeLeft(10);
assertTrue("UiObject swipe left 2->3", "[ 3 ]".equals(textView.getText()));
textView.swipeLeft(10);
assertTrue("UiObject swipe left 3->4", "[ 4 ]".equals(textView.getText()));
textView.swipeRight(10);
assertTrue("UiObject swipe right 3<-4", "[ 3 ]".equals(textView.getText()));
textView.swipeRight(10);
assertTrue("UiObject swipe right 2<-3", "[ 2 ]".equals(textView.getText()));
textView.swipeRight(10);
assertTrue("UiObject swipe right 1<-2", "[ 1 ]".equals(textView.getText()));
Rect tb = textView.getBounds();
UiDevice.getInstance().swipe(tb.right - 20, tb.centerY(), tb.left + 20, tb.centerY(), 50);
SystemClock.sleep(100);
assertTrue("UiDevice raw swipe 1->2", "[ 2 ]".equals(textView.getText()));
}
/**
* Creates a complex selector
*
* @throws UiObjectNotFoundException
*/
public void testComplexSelectors() throws UiObjectNotFoundException {
openTest("Test 5");
UiSelector frameLayout = new UiSelector().className(android.widget.FrameLayout.class
.getName());
UiSelector gridLayout = new UiSelector().className(android.widget.GridLayout.class
.getName());
UiSelector toggleButton = new UiSelector().className(android.widget.ToggleButton.class
.getName());
UiObject button = new UiObject(frameLayout.childSelector(gridLayout).childSelector(
toggleButton));
assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
button.click();
assertTrue("Toggle button value should be ON", "ON".equals(button.getText()));
button.click();
assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
}
/**
* Test when an object does not exist, an exception is thrown
* @throws UiObjectNotFoundException
*/
public void testExceptionObjectNotFound() throws UiObjectNotFoundException {
UiSelector selector = new UiSelector().text("Nothing should be found");
UiSelector child = new UiSelector().className("Nothing");
UiObject obj = new UiObject(selector.childSelector(child));
assertFalse("Object is reported as existing", obj.exists());
try {
obj.click();
} catch (UiObjectNotFoundException e) {
return;
}
assertTrue("Exception not thrown for Object not found", false);
}
/**
* Verifies the UiWatcher registration and trigger function
*
* @throws UiObjectNotFoundException
*/
public void testUiWatcher() throws UiObjectNotFoundException {
openTest("Test 5");
UiDevice device = UiDevice.getInstance();
device.registerWatcher("Artificial crash", new UiWatcher() {
@Override
public boolean checkForCondition() {
if (new UiObject(new UiSelector().packageName("android")).exists()) {
try {
// Expecting a localized OK button
new UiObject(new UiSelector().className(
android.widget.Button.class.getName()).enabled(true)).click();
} catch (UiObjectNotFoundException e) {
}
return true;
}
return false;
}
});
// Causes a runtime exception to be thrown
getObjectByText("Button").click();
// Fake doing something while the exception is being displayed
SystemClock.sleep(2000);
device.runWatchers();
assertTrue("UiWatcher not triggered", device.hasAnyWatcherTriggered());
}
/**
* Verifies the 'checked' property of both UiSelector and UiObject
*
* @throws UiObjectNotFoundException
*/
public void testSelectorChecked() throws UiObjectNotFoundException {
openTest("Test 5");
UiObject checkboxChecked = new UiObject(new UiSelector().className(
android.widget.CheckBox.class.getName()).checked(true));
UiObject checkboxNotChecked = new UiObject(new UiSelector().className(
android.widget.CheckBox.class.getName()).checked(false));
checkboxNotChecked.click();
assertTrue("Checkbox should be checked", checkboxChecked.isChecked());
checkboxChecked.click();
assertFalse("Checkbox should be unchecked", checkboxNotChecked.isChecked());
}
/**
* Verifies the 'Clickable' property of both the UiSelector and UiObject
*
* @throws UiObjectNotFoundException
*/
public void testSelectorClickable() throws UiObjectNotFoundException {
openTest("Test 5");
UiSelector clickableCheckbox = new UiSelector().clickable(true).className(
android.widget.CheckBox.class.getName());
UiSelector notClickableProgress = new UiSelector().clickable(false).className(
android.widget.ProgressBar.class.getName());
assertTrue("Selector clickable", new UiObject(clickableCheckbox).isClickable());
assertFalse("Selector not clickable", new UiObject(notClickableProgress).isClickable());
}
/**
* Verifies the 'focusable' property of both UiSelector and UiObject
*
* @throws UiObjectNotFoundException
*/
public void testSelectorFocusable() throws UiObjectNotFoundException {
openTest("Test 5");
UiSelector mainLayout = new UiSelector().description("Widgets Collection");
UiSelector focusableCheckbox = mainLayout.childSelector(new UiSelector().className(
android.widget.CheckBox.class.getName()).focusable(true));
UiSelector notFocusableSpinner = mainLayout.childSelector(new UiSelector().className(
android.widget.Spinner.class.getName()).focusable(false));
assertTrue("Selector focusable", new UiObject(focusableCheckbox).isFocusable());
assertFalse("Selector not focusable", new UiObject(notFocusableSpinner).isFocusable());
}
/**
* Verifies the 'DescriptionContains' property of UiSelector
*
* @throws UiObjectNotFoundException
*/
public void testSelectorDescriptionContains() throws UiObjectNotFoundException {
openTest("Test 5");
UiSelector progressDescriptionContains = new UiSelector().descriptionContains("%");
assertTrue("Selector descriptionContains", "Progress is 50 %".equals(new UiObject(
progressDescriptionContains).getContentDescription()));
}
/**
* Verifies the 'DescriptionStarts' property of UiSelector
*
* @throws UiObjectNotFoundException
*/
public void testSelectorDescriptionStarts() throws UiObjectNotFoundException {
openTest("Test 5");
UiSelector progressDescriptionStart = new UiSelector().descriptionStartsWith("progress");
assertTrue("Selector descriptionStart", "Progress is 50 %".equals(new UiObject(
progressDescriptionStart).getContentDescription()));
}
/**
* Verifies the 'Enabled' property of both UiSelector and UiObject
*
* @throws UiObjectNotFoundException
*/
public void testSelectorEnabled() throws UiObjectNotFoundException {
openTest("Test 5");
UiSelector mainLayout = new UiSelector().description("Widgets Collection");
UiSelector buttonDisabled = mainLayout.childSelector(new UiSelector().className(
android.widget.Button.class.getName()).enabled(false));
UiSelector buttonEnabled = mainLayout.childSelector(new UiSelector().className(
android.widget.Button.class.getName()).enabled(true));
assertFalse("Selector enabled false", new UiObject(buttonDisabled).isEnabled());
assertTrue("Selector enabled true", new UiObject(buttonEnabled).isEnabled());
}
/**
* Verifies the UiCollection object child counting by object pattern
*
* @throws UiObjectNotFoundException
*/
public void testCollectionCount() throws UiObjectNotFoundException {
openTest("Test 5");
UiCollection collection = new UiCollection(
new UiSelector().description("Widgets Collection"));
assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
assertTrue("Collection count",
collection.getChildCount(new UiSelector().clickable(true)) == 6);
}
/**
* Verifies the UiCollection can find an object by text and returning by
* pattern
*
* @throws UiObjectNotFoundException
*/
public void testCollectionGetChildByText() throws UiObjectNotFoundException {
openTest("Test 5");
UiCollection collection = new UiCollection(
new UiSelector().description("Widgets Collection"));
assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
UiObject item = collection.getChildByText(
new UiSelector().className(android.widget.Button.class.getName()), "Button");
assertTrue("Collection get child by text", "Button".equals(item.getText()));
}
/**
* Verifies the UiCollection can find an object by instance and returning by
* pattern
*
* @throws UiObjectNotFoundException
*/
public void testCollectionGetChildByInstance() throws UiObjectNotFoundException {
openTest("Test 5");
UiCollection collection = new UiCollection(
new UiSelector().description("Widgets Collection"));
assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
// find the second button
UiObject item = collection.getChildByInstance(
new UiSelector().className(android.widget.Button.class.getName()), 1);
assertTrue("Collection get child by instance", "Button".equals(item.getText()));
}
/**
* Verifies the UiCollection can find an object by description and returning
* by pattern
*
* @throws UiObjectNotFoundException
*/
public void testCollectionGetChildByDescription() throws UiObjectNotFoundException {
openTest("Test 5");
UiCollection collection = new UiCollection(
new UiSelector().description("Widgets Collection"));
assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
UiObject item = collection.getChildByDescription(
new UiSelector().className(android.widget.Button.class.getName()),
"Description for Button");
assertTrue("Collection get child by description", "Button".equals(item.getText()));
}
/**
* 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 {
openTest("Test 2");
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 = getInstrumentation().getContext().getFileStreamPath(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);
}
/**
* Verifies the 'Resource-Id' property of UiSelector
*
* @throws UiObjectNotFoundException
* @since API Level 18
*/
public void testSelectorResourceId() throws UiObjectNotFoundException {
openTest("Test 5");
UiSelector toggleSelector =
new UiSelector().resourceId("com.android.uiautomator.tests.cts.testapp:id/test_5_toggleButton");
UiObject toggleButton = new UiObject(toggleSelector);
assertTrue("Object with selector resource-id not found", toggleButton.exists());
assertTrue("Incorrect object for selector resource-id returned",
"OFF".equals(toggleButton.getText()) || "ON".equals(toggleButton.getText()));
}
/**
* Verify the UiSelector property resourceIdMatches
*
* @throws UiObjectNotFoundException
* @since API Level 18
*/
public void testSelectorResourceIdMatches() throws UiObjectNotFoundException {
openTest("Test 2");
new UiObject(new UiSelector().resourceIdMatches("(?i).*button.*").instance(2)).click();
verifyDialogActionResults("Button 3");
new UiObject(new UiSelector().resourceIdMatches("(?i).*button1.*")).click();
verifyDialogActionResults("Button 1");
}
/**
* Performs a pinch out from the center of a view to its edges and listens to
* the motion events to make sure the starting and ending points of both pointers
* are correct.
*
* @throws UiObjectNotFoundException
* @since API Level 18
*/
public void testPinchOut() throws UiObjectNotFoundException {
openTest("Test 12");
UiObject screen = new UiObject(
new UiSelector().description("Details View"));
// get the current view dimensions
Rect screenRect = screen.getBounds();
// perform the pinch for 100% of the view dimensions starting form
// the center out to the edges.
screen.pinchOut(100, 30);
// dialog with the detected pointers motion coordinates is displayed.
UiObject results = new UiObject(new UiSelector().className(
android.widget.ScrollView.class).childSelector(new UiSelector().className(
android.widget.TextView.class)));
String allPointers = results.getText();
new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
// parse pointer 1
Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
// parse pointer 2
Point p2s = parsePointerCoordinates(allPointers, 1, 0); // start
Point p2e = parsePointerCoordinates(allPointers, 1, 1); // end
assertTrue("All Y axis coordinates for pointer 1 must be the same", p1s.y == p1e.y);
assertTrue("All Y axis coordinates for pointer 2 must be the same", p2s.y == p2e.y);
assertTrue("All Y axis coordinates for both pointers must be the same", p1s.y == p2s.y);
assertTrue("Pinch must be in center of target view", p2s.y == screenRect.centerY());
assertTrue("Touch-down X coordinate for pointer 1 is invalid",
withinMarginOfError(0.1f, screenRect.centerX(), p1s.x));
assertTrue("Touch-down X coordinate for pointer 2 is invalid",
withinMarginOfError(0.1f, screenRect.centerX(), p2s.x));
assertTrue("Touch-up X coordinate for pointer 1 is invalid",
withinMarginOfError(0.1f, screenRect.centerX() - screenRect.left,
screenRect.centerX() - p1e.x));
assertTrue("Touch-up X coordinate for pointer 2 is invalid",
withinMarginOfError(0.1f, screenRect.right, p2e.x));
}
/**
* Performs a pinch in from the edges of a view to its center and listens to
* the motion events to make sure the starting and ending points of both pointers
* are correct.
*
* @throws UiObjectNotFoundException
* @since API Level 18
*/
public void testPinchIn() throws UiObjectNotFoundException {
openTest("Test 12");
UiObject screen = new UiObject(
new UiSelector().description("Details View"));
// get the current view dimensions
Rect screenRect = screen.getBounds();
// perform the pinch for 100% of the view dimensions starting form
// the edges in towards the center.
screen.pinchIn(100, 30);
// dialog with the detected pointers motion coordinates is displayed.
UiObject results = new UiObject(new UiSelector().className(
android.widget.ScrollView.class).childSelector(new UiSelector().className(
android.widget.TextView.class)));
String allPointers = results.getText();
new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
// parse pointer 1
Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
// parse pointer 2
Point p2s = parsePointerCoordinates(allPointers, 1, 0); // start
Point p2e = parsePointerCoordinates(allPointers, 1, 1); // end
assertTrue("All Y axis coordinates for pointer 1 must be the same", p1s.y == p1e.y);
assertTrue("All Y axis coordinates for pointer 2 must be the same", p2s.y == p2e.y);
assertTrue("All Y axis coordinates for both pointers must be the same", p1s.y == p2s.y);
assertTrue("Pinch must be in center of target view", p2s.y == screenRect.centerY());
assertTrue("Touch-down X coordinate for pointer 1 is invalid",
withinMarginOfError(0.1f, screenRect.centerX() - screenRect.left,
screenRect.centerX() - p1s.x));
assertTrue("Touch-down X coordinate for pointer 2 is invalid",
withinMarginOfError(0.1f, screenRect.right, p2s.x));
assertTrue("Touch-up X coordinate for pointer 1 is invalid",
withinMarginOfError(0.1f, screenRect.centerX(), p1e.x));
assertTrue("Touch-up X coordinate for pointer 2 is invalid",
withinMarginOfError(0.1f, screenRect.centerX(), p2e.x));
}
/**
* Performs a drag and drop operation from one UiObject to another UiObject
*
* @throws UiObjectNotFoundException
* @since API Level 18
*/
public void testDragToObject() throws UiObjectNotFoundException {
openTest("Test 5");
UiObject imageButton = new UiObject(new UiSelector().description("Image button"));
UiObject starsBar = new UiObject(new UiSelector().className(android.widget.RatingBar.class));
Rect starsBarRect = starsBar.getBounds();
Rect imageButtonRect = imageButton.getBounds();
imageButton.dragTo(starsBar, 30);
// dialog with the detected pointers motion coordinates is displayed.
UiObject results = new UiObject(new UiSelector().className(
android.widget.ScrollView.class).childSelector(new UiSelector().className(
android.widget.TextView.class)));
String allPointers = results.getText();
new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
// parse pointer 1
Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
assertTrue("Invalid touch starting.X reported",
withinMarginOfError(0.05f, imageButtonRect.centerX(), p1s.x));
assertTrue("Invalid touch starting.Y reported",
withinMarginOfError(0.05f, imageButtonRect.centerY(), p1s.y));
assertTrue("Invalid touch ending.X reported",
withinMarginOfError(0.05f, starsBarRect.centerX(), p1e.x));
assertTrue("Invalid touch ending.Y reported",
withinMarginOfError(0.05f, starsBarRect.centerY(), p1e.y));
}
/**
* Performs a drag and drop operation from one UiObject to a specified coordinates
*
* @throws UiObjectNotFoundException
* @since API Level 18
*/
public void testDragToCoordinates() throws UiObjectNotFoundException {
openTest("Test 5");
UiObject imageButton = new UiObject(new UiSelector().description("Image button"));
UiObject starsBar = new UiObject(new UiSelector().className(android.widget.RatingBar.class));
Rect starsBarRect = starsBar.getBounds();
Rect imageButtonRect = imageButton.getBounds();
imageButton.dragTo(starsBarRect.centerX(), starsBarRect.centerY(), 30);
// dialog with the detected pointers motion coordinates is displayed.
UiObject results = new UiObject(new UiSelector().className(
android.widget.ScrollView.class).childSelector(new UiSelector().className(
android.widget.TextView.class)));
String allPointers = results.getText();
new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
// parse pointer 1
Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
assertTrue("Invalid touch starting.X reported",
withinMarginOfError(0.05f, imageButtonRect.centerX(), p1s.x));
assertTrue("Invalid touch starting.Y reported",
withinMarginOfError(0.05f, imageButtonRect.centerY(), p1s.y));
assertTrue("Invalid touch ending.X reported",
withinMarginOfError(0.05f, starsBarRect.centerX(), p1e.x));
assertTrue("Invalid touch ending.Y reported",
withinMarginOfError(0.05f, starsBarRect.centerY(), p1e.y));
}
/**
* Detect if actual value is within the allowable margin of error of the expected value.
*
* Used essentially with actual values that may vary from the expected values such in the
* cases of touch and pinch and touch and swipe where the starting or ending points may
* not exactly match the expected value.
*
* @param marginPrecent is values between 0 and 1
* @param expected
* @param actual
* @return true if actual is within the allowed range from expected
*/
private boolean withinMarginOfError(float marginPrecent, int expected, int actual) {
int m = (int) (marginPrecent * expected);
return actual >= expected - m && actual <= expected + m;
}
/**
* Parses a string containing starting to ending coordinates of one or more pointers.
*
* @param allPointers is a raw string with coordinates from all detected pointers
* @param pointerNumber is the desired pointer to be parsed
* @param edge is the 0 for the start or 1 for the end of the swipe
* @return Point containing the start or end coordinates of the specified pointer number
*/
private Point parsePointerCoordinates(String allPointers, int pointerNumber, int edge) {
String pointers[] = allPointers.split("\n");
String coordinates = pointers[pointerNumber].split(":")[edge];
String xy[] = coordinates.split(",");
return new Point(Integer.parseInt(xy[0]), Integer.parseInt(xy[1]));
}
/**
* Private helper to open test views. Also covers UiScrollable tests
*
* @param name
* @throws UiObjectNotFoundException
*/
private void openTest(String name) throws UiObjectNotFoundException {
try {
UiDevice.getInstance().setOrientationNatural();
} catch (RemoteException e) {
// will catch it in its own test. For now try to put the device
// in its natural orientation prior to each test
}
UiScrollable listView = new UiScrollable(
new UiSelector().className(android.widget.ListView.class.getName()));
// on single fragment display
if (!listView.exists())
UiDevice.getInstance().pressBack();
UiObject testItem = listView.getChildByText(
new UiSelector().className(android.widget.TextView.class.getName()), name);
testItem.click();
}
private void verifyTestDetailsExists(String name) throws UiObjectNotFoundException {
// verify that we're at the right test
new UiObject(new UiSelector().description("Details").text(name)).getText();
}
private UiObject getObjectByText(String txt) {
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));
}
private UiObject getObjectByInstance(String className, int instance) {
return new UiObject(new UiSelector().className(className).instance(instance));
}
private void verifyDialogActionResults(String txt) throws UiObjectNotFoundException {
if (!getObjectByText("Action results").exists() || !getObjectByText(txt).exists()) {
throw new UiObjectNotFoundException(txt);
}
getObjectByText("OK").click();
}
}