diff options
author | Allen Hair <allenhair@google.com> | 2013-10-24 12:34:59 -0700 |
---|---|---|
committer | Allen Hair <allenhair@google.com> | 2013-10-25 12:48:41 -0700 |
commit | abb2af7d5f4912905cf105466f34ae983310c47b (patch) | |
tree | a3e9ddde64f9b6230bff5c30829cb05c71ab0707 | |
parent | 61ce05bd4fd5ffc1f036c7c02c9af7cb92d6ec50 (diff) | |
download | uiautomator-abb2af7d5f4912905cf105466f34ae983310c47b.tar.gz |
Port UiAutomator CTS test to the unbundled branch.
Copied test from cts/tests/uiautomator. Modified the code to use the
instrumentation based uiautomator rather than shell based.
Change-Id: I8db4ac24d64813aa58fda42abff7b81bcedf70f3
53 files changed, 3458 insertions, 0 deletions
@@ -116,3 +116,7 @@ uiautomator_library := uiautomator_api_dir := checkapi_last_error_level_flags := checkapi_current_error_level_flags := + +############################################### +# Build tests +include $(LOCAL_PATH)/tests/Android.mk diff --git a/tests/Android.mk b/tests/Android.mk new file mode 100644 index 0000000..260fae2 --- /dev/null +++ b/tests/Android.mk @@ -0,0 +1,15 @@ +# 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. + +include $(call all-subdir-makefiles) diff --git a/tests/CtsUiAutomatorTest/Android.mk b/tests/CtsUiAutomatorTest/Android.mk new file mode 100644 index 0000000..9d06bae --- /dev/null +++ b/tests/CtsUiAutomatorTest/Android.mk @@ -0,0 +1,29 @@ +# 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. + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_PACKAGE_NAME := UbCtsUiAutomatorTest +LOCAL_MODULE_TAGS := tests +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_SDK_VERSION := 18 + +LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator + +include $(BUILD_PACKAGE) + +# Build the test APK using its own makefile, and any other CTS-related packages +include $(call all-makefiles-under, $(LOCAL_PATH)) diff --git a/tests/CtsUiAutomatorTest/AndroidManifest.xml b/tests/CtsUiAutomatorTest/AndroidManifest.xml new file mode 100644 index 0000000..c8207db --- /dev/null +++ b/tests/CtsUiAutomatorTest/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.uiautomator.tests.cts"> + + <uses-sdk android:minSdkVersion="18" /> + + <application> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation + android:name="com.android.uiautomator.testrunner.UiAutomatorInstrumentationTestRunner" + android:targetPackage="com.android.uiautomator.tests.cts" + android:label="UiAutomator Tests"/> + +</manifest> diff --git a/tests/CtsUiAutomatorTest/src/com/android/uiautomator/tests/cts/CtsUiAutomatorTest.java b/tests/CtsUiAutomatorTest/src/com/android/uiautomator/tests/cts/CtsUiAutomatorTest.java new file mode 100644 index 0000000..65e7b9d --- /dev/null +++ b/tests/CtsUiAutomatorTest/src/com/android/uiautomator/tests/cts/CtsUiAutomatorTest.java @@ -0,0 +1,1046 @@ +/* + * 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(); + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/Android.mk b/tests/CtsUiAutomatorTest/testapp/Android.mk new file mode 100644 index 0000000..ef5801e --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/Android.mk @@ -0,0 +1,33 @@ +# 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. + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_SDK_VERSION := 18 + +LOCAL_PACKAGE_NAME := UbCtsUiAutomatorTestApp +LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 + +LOCAL_PROGUARD_ENABLED := disabled + +LOCAL_DEX_PREOPT := false + +include $(BUILD_PACKAGE) diff --git a/tests/CtsUiAutomatorTest/testapp/AndroidManifest.xml b/tests/CtsUiAutomatorTest/testapp/AndroidManifest.xml new file mode 100644 index 0000000..bc80e26 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/AndroidManifest.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.uiautomator.tests.cts.testapp" + android:versionCode="1" + android:versionName="1.0" > + <uses-sdk + android:minSdkVersion="14" + android:targetSdkVersion="15" /> + + <uses-permission android:name="android.permission.INTERNET"/> + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:theme="@style/AppTheme" > + <activity + android:name=".MainActivity" + android:label="@string/title_test_list" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <activity + android:name=".SinglePaneDetailActivity" + android:label="@string/title_test_detail" > + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value="FragmentActivity" /> + </activity> + </application> + +</manifest> diff --git a/tests/CtsUiAutomatorTest/testapp/res/drawable-hdpi/ic_action_search.png b/tests/CtsUiAutomatorTest/testapp/res/drawable-hdpi/ic_action_search.png Binary files differnew file mode 100644 index 0000000..67de12d --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/drawable-hdpi/ic_action_search.png diff --git a/tests/CtsUiAutomatorTest/testapp/res/drawable-hdpi/ic_launcher.png b/tests/CtsUiAutomatorTest/testapp/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..947dbfc --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/drawable-hdpi/ic_launcher.png diff --git a/tests/CtsUiAutomatorTest/testapp/res/drawable-ldpi/ic_launcher.png b/tests/CtsUiAutomatorTest/testapp/res/drawable-ldpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..e075065 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/drawable-ldpi/ic_launcher.png diff --git a/tests/CtsUiAutomatorTest/testapp/res/drawable-mdpi/ic_action_search.png b/tests/CtsUiAutomatorTest/testapp/res/drawable-mdpi/ic_action_search.png Binary files differnew file mode 100644 index 0000000..134d549 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/drawable-mdpi/ic_action_search.png diff --git a/tests/CtsUiAutomatorTest/testapp/res/drawable-mdpi/ic_launcher.png b/tests/CtsUiAutomatorTest/testapp/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..f91af33 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/drawable-mdpi/ic_launcher.png diff --git a/tests/CtsUiAutomatorTest/testapp/res/drawable-xhdpi/ic_action_search.png b/tests/CtsUiAutomatorTest/testapp/res/drawable-xhdpi/ic_action_search.png Binary files differnew file mode 100644 index 0000000..d699c6b --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/drawable-xhdpi/ic_action_search.png diff --git a/tests/CtsUiAutomatorTest/testapp/res/drawable-xhdpi/ic_launcher.png b/tests/CtsUiAutomatorTest/testapp/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..542a9cb --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/drawable-xhdpi/ic_launcher.png diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/activity_main.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/activity_main.xml new file mode 100644 index 0000000..6b7f72f --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/activity_main.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MainActivity" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_centerVertical="true" + android:text="@string/hello_world" /> + +</RelativeLayout> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/list_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/list_activity.xml new file mode 100644 index 0000000..9593e07 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/list_activity.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<fragment xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:name="com.android.uiautomator.tests.cts.testapp.TestListFragment" + android:id="@+id/item_list" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginLeft="16dp" + android:layout_marginRight="16dp" + tools:context=".MainActivity" /> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/simple_list_item_selected.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/simple_list_item_selected.xml new file mode 100644 index 0000000..f0b0644 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/simple_list_item_selected.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/label" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceListItemSmall" + android:gravity="center_vertical" + android:paddingLeft="?android:attr/listPreferredItemPaddingLeft" + android:paddingRight="?android:attr/listPreferredItemPaddingRight" + android:background="?android:attr/activatedBackgroundIndicator" + android:minHeight="?android:attr/listPreferredItemHeightSmall" +/> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/singlepane_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/singlepane_activity.xml new file mode 100644 index 0000000..7ebcb7d --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/singlepane_activity.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/test_results_detail_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".TestResultsDetailActivity" /> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/test1_detail_fragment.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/test1_detail_fragment.xml new file mode 100644 index 0000000..e157940 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/test1_detail_fragment.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/test_1_detail_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <TextView + android:id="@+id/item1_test_description" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="5dp" + android:text="@string/test1_description" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" > + + <EditText + android:id="@+id/test1TextField" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_marginLeft="5dp" + android:layout_weight="2" + android:inputType="textNoSuggestions" + android:paddingLeft="5dip" + android:paddingRight="5dip" + android:width="200dip" > + + <requestFocus /> + </EditText> + + <Button + android:id="@+id/test1SubmitButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="5dip" + android:layout_marginRight="5dip" + android:minWidth="64dip" + android:text="@string/buttonSubmit" /> + + </LinearLayout> + +</LinearLayout> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/test2_detail_fragment.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/test2_detail_fragment.xml new file mode 100644 index 0000000..2bc397d --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/test2_detail_fragment.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/test_2_detail_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="5dp" + android:text="@string/test2_description" /> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:orientation="horizontal" > + + <Button + android:id="@+id/test2button1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/button1" + android:text="@string/button1" /> + + <Button + android:id="@+id/test2button2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/button2" + android:text="@string/button2" /> + + <Button + android:id="@+id/test2button3" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/button3" + android:text="@string/button3" /> + </LinearLayout> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="5dp" + android:text="@string/test2_description_2" /> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:orientation="horizontal" > + + <Button + android:id="@+id/test2dynaButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/buttonBefore" + android:text="@string/buttonBefore" /> + + </LinearLayout> +</LinearLayout> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/test3_detail_fragment.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/test3_detail_fragment.xml new file mode 100644 index 0000000..1e7c930 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/test3_detail_fragment.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/test_3_detail_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <TextView + android:id="@+id/item3_test_description" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="5dp" + android:text="@string/test3_description" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <TextView + android:id="@+id/test3ClockTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="10dip" + android:layout_marginTop="10dip" + android:contentDescription="@string/test3ClockDescription" + android:padding="10dp" + android:text="@string/test3InitialClock" /> + + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" > + + <EditText + android:id="@+id/test3TextField" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_marginLeft="5dp" + android:layout_weight="2" + android:inputType="numberDecimal" + android:paddingLeft="5dip" + android:paddingRight="5dip" + android:width="200dip" > + <requestFocus /> + </EditText> + + <Button + android:id="@+id/test3SubmitButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="5dip" + android:layout_marginRight="5dip" + android:minWidth="64dip" + android:text="@string/buttonSubmit" /> + </LinearLayout> +</LinearLayout> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/test4_detail_fragment.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/test4_detail_fragment.xml new file mode 100644 index 0000000..fc19b81 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/test4_detail_fragment.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> + <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/test_4_detail_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".Test4DetailActivity" /> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/test5_detail_fragment.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/test5_detail_fragment.xml new file mode 100644 index 0000000..51fe2f1 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/test5_detail_fragment.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:contentDescription="@string/test_5_Widgets_collection" + android:orientation="vertical" > + + <CheckBox + android:id="@+id/test_5_checkBox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/test5_CheckBox" /> + + <Spinner + android:id="@+id/test_5_spinner" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <ProgressBar + android:id="@+id/test_5_progressBar" + style="?android:attr/progressBarStyleLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <GridLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:columnCount="3" > + + <ImageButton + android:id="@+id/test_5_imageButton" + android:layout_column="0" + android:layout_gravity="left" + android:layout_row="0" + android:src="@drawable/ic_launcher" /> + + <RatingBar + android:id="@+id/test_5_ratingBar" + android:layout_column="1" + android:layout_columnSpan="2" + android:layout_gravity="left|bottom" + android:layout_row="0" /> + + <Button + android:id="@+id/test_5_button2" + style="?android:attr/buttonStyleSmall" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="left|bottom" + android:enabled="false" + android:layout_row="0" + android:text="@string/test5_Button_Disabled" /> + + <Space + android:layout_width="21dp" + android:layout_height="1dp" + android:layout_column="1" + android:layout_row="0" /> + + <Space + android:layout_width="1dp" + android:layout_height="21dp" + android:layout_column="0" + android:layout_row="0" /> + + <Space + android:layout_width="221dp" + android:layout_height="15dp" + android:layout_column="2" + android:layout_row="1" /> + + <ToggleButton + android:id="@+id/test_5_toggleButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_column="2" + android:text="@string/test5_ToggleButton" /> + </GridLayout> + + <SeekBar + android:id="@+id/test_5_seekBar" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + <Button + android:id="@+id/test_5_button1" + style="?android:attr/buttonStyleSmall" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/test5_Button_Description" + android:text="@string/test5_Button" /> + +</LinearLayout> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/test6_detail_fragment.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/test6_detail_fragment.xml new file mode 100644 index 0000000..49e6b8c --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/test6_detail_fragment.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <WebView + android:id="@+id/test6WebView" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + +</LinearLayout> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/test_results_detail_fragment.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/test_results_detail_fragment.xml new file mode 100644 index 0000000..e68f54a --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/test_results_detail_fragment.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/test_results_detail_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:contentDescription="@string/title_test_view_detail" + android:orientation="vertical" > + + <TextView + android:id="@+id/textView1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:padding="5dp" + android:text="@string/now_displaying_results_for" /> + + <TextView + android:id="@+id/testResultsTextView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:contentDescription="@string/title_test_detail" + android:paddingLeft="2dp" + android:paddingTop="5dp" + android:textColor="#00aa00" + android:textSize="@dimen/padding_large" + android:textStyle="bold" /> + +</LinearLayout> diff --git a/tests/CtsUiAutomatorTest/testapp/res/layout/twopane_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/layout/twopane_activity.xml new file mode 100644 index 0000000..b970961 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/layout/twopane_activity.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginLeft="16dp" + android:layout_marginRight="16dp" + android:divider="?android:attr/dividerHorizontal" + android:showDividers="middle" + tools:context=".TestListActivity"> + + <fragment + android:id="@+id/item_list" + android:name="com.android.uiautomator.tests.cts.testapp.TestListFragment" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="1" /> + + <FrameLayout android:id="@+id/test_detail_container" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="3" /> + +</LinearLayout> diff --git a/tests/CtsUiAutomatorTest/testapp/res/menu/activity_main.xml b/tests/CtsUiAutomatorTest/testapp/res/menu/activity_main.xml new file mode 100644 index 0000000..37c04bd --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/menu/activity_main.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<menu xmlns:android="http://schemas.android.com/apk/res/android" > + + <item + android:id="@+id/menu_settings" + android:orderInCategory="100" + android:showAsAction="never" + android:title="@string/menu_settings"/> + +</menu> diff --git a/tests/CtsUiAutomatorTest/testapp/res/menu/test1_detail_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/menu/test1_detail_activity.xml new file mode 100644 index 0000000..0b776bb --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/menu/test1_detail_activity.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_settings" + android:title="@string/menu_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> diff --git a/tests/CtsUiAutomatorTest/testapp/res/menu/test2_detail_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/menu/test2_detail_activity.xml new file mode 100644 index 0000000..ce0ca49 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/menu/test2_detail_activity.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_text1" + android:title="Submit" /> + <item android:id="@+id/menu_text2" + android:icon="@drawable/ic_launcher" + android:title="Done" /> + <item android:id="@+id/menu_text3" + android:title="OK" /> + <item android:id="@+id/menu_text4" + android:title="Finish" /> + <item android:id="@+id/menu_text5" + android:title="Complete" /> + <item android:id="@+id/menu_text6" + android:title="Exit" /> +</menu> diff --git a/tests/CtsUiAutomatorTest/testapp/res/menu/test3_detail_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/menu/test3_detail_activity.xml new file mode 100644 index 0000000..0b776bb --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/menu/test3_detail_activity.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_settings" + android:title="@string/menu_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> diff --git a/tests/CtsUiAutomatorTest/testapp/res/menu/test4_detail_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/menu/test4_detail_activity.xml new file mode 100644 index 0000000..0b776bb --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/menu/test4_detail_activity.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_settings" + android:title="@string/menu_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> diff --git a/tests/CtsUiAutomatorTest/testapp/res/menu/test5_detail_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/menu/test5_detail_activity.xml new file mode 100644 index 0000000..0b776bb --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/menu/test5_detail_activity.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_settings" + android:title="@string/menu_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> diff --git a/tests/CtsUiAutomatorTest/testapp/res/menu/test6_detail_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/menu/test6_detail_activity.xml new file mode 100644 index 0000000..0b776bb --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/menu/test6_detail_activity.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_settings" + android:title="@string/menu_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> diff --git a/tests/CtsUiAutomatorTest/testapp/res/menu/test_results_detail_activity.xml b/tests/CtsUiAutomatorTest/testapp/res/menu/test_results_detail_activity.xml new file mode 100644 index 0000000..3bf852f --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/menu/test_results_detail_activity.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_settings" + android:title="@string/menu_settings" + android:orderInCategory="100" + android:showAsAction="never" /> +</menu> + diff --git a/tests/CtsUiAutomatorTest/testapp/res/values-large/dimens.xml b/tests/CtsUiAutomatorTest/testapp/res/values-large/dimens.xml new file mode 100644 index 0000000..d1ffde5 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/values-large/dimens.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<resources> + + <dimen name="padding_small">8dp</dimen> + <dimen name="padding_medium">16dp</dimen> + <dimen name="padding_large">16dp</dimen> + +</resources> diff --git a/tests/CtsUiAutomatorTest/testapp/res/values-large/refs.xml b/tests/CtsUiAutomatorTest/testapp/res/values-large/refs.xml new file mode 100644 index 0000000..7431c8b --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/values-large/refs.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<resources> + <item type="layout" name="list_activity">@layout/twopane_activity</item> +</resources> diff --git a/tests/CtsUiAutomatorTest/testapp/res/values-sw600dp/refs.xml b/tests/CtsUiAutomatorTest/testapp/res/values-sw600dp/refs.xml new file mode 100644 index 0000000..7431c8b --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/values-sw600dp/refs.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<resources> + <item type="layout" name="list_activity">@layout/twopane_activity</item> +</resources> diff --git a/tests/CtsUiAutomatorTest/testapp/res/values-v11/styles.xml b/tests/CtsUiAutomatorTest/testapp/res/values-v11/styles.xml new file mode 100644 index 0000000..a9a67e9 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/values-v11/styles.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<resources> + + <style name="AppTheme" parent="android:Theme.Holo.Light" /> + +</resources> diff --git a/tests/CtsUiAutomatorTest/testapp/res/values-v14/styles.xml b/tests/CtsUiAutomatorTest/testapp/res/values-v14/styles.xml new file mode 100644 index 0000000..3cbff5f --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/values-v14/styles.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<resources> + + <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" /> + +</resources> diff --git a/tests/CtsUiAutomatorTest/testapp/res/values/dimens.xml b/tests/CtsUiAutomatorTest/testapp/res/values/dimens.xml new file mode 100644 index 0000000..cfbac7a --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/values/dimens.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<resources> + + <dimen name="padding_small">8dp</dimen> + <dimen name="padding_medium">8dp</dimen> + <dimen name="padding_large">16dp</dimen> + +</resources> diff --git a/tests/CtsUiAutomatorTest/testapp/res/values/strings.xml b/tests/CtsUiAutomatorTest/testapp/res/values/strings.xml new file mode 100644 index 0000000..4ac5243 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/values/strings.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * 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. + --> +<resources> + + <string name="app_name">UiAutomator Test App</string> + <string name="test1_description">This helps verify entering text into a pre-populated field. The pop-up dialog will echo the text entered after clicking submit. The initial value in the field must first be deleted.</string> + <string name="menu_settings">Settings</string> + <string name="title_activity_item1_detail">Item1DetailActivity</string> + <string name="buttonSubmit">Submit</string> + <string name="item1_dialog_title">Text submitted</string> + <string name="OK">OK</string> + <string name="title_test_list">UiAutomator Tests</string> + <string name="title_test_detail">Details</string> + <string name="hello_world">Hello world!</string> + <string name="title_activity_test2_detail">Test2DetailActivity</string> + <string name="test2_description">This helps test selection of button using Instance, Text and Content Description. Once clicked, a dialog pops up to verify the properties of button clicked.</string> + <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> + <string name="now_displaying_results_for">Verifying scroll into view and list item selection. Now displaying results for:</string> + <string name="title_activity_test3_detail">Performance test</string> + <string name="test3ClockDescription">Performance clock</string> + <string name="test3InitialClock">0000000000</string> + <string name="test3_dialog_title">Time difference in ms</string> + <string name="test5_CheckBox">CheckBox</string> + <string name="test5_ToggleButton">ToggleButton</string> + <string name="test5_Button">Button</string> + <string name="test5_Button_Description">Description for Button</string> + <string name="test5_Button_Disabled">Button D</string> + <string name="title_section4">Section 4</string> + <string name="title_section3">Section 3</string> + <string name="title_section2">Section 2</string> + <string name="title_section1">Section 1</string> + <string name="title_activity_test4_detail">Test4DetailActivity</string> + <string name="title_activity_test5_detail">Test5DetailActivity</string> + <string name="title_activity_test6_detail">Test6DetailActivity</string> + <string name="test_5_Widgets_collection">Widgets Collection</string> + <string name="generic_item_touch_dialog_title">Multi-touch test dialog</string> + <string name="drag_item_touch_dialog_title">Drag and drop test dialog</string> + <string name="title_test_view_detail">Details View</string> +</resources> diff --git a/tests/CtsUiAutomatorTest/testapp/res/values/styles.xml b/tests/CtsUiAutomatorTest/testapp/res/values/styles.xml new file mode 100644 index 0000000..ab1a580 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/res/values/styles.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * 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. + --> +<resources> + + <style name="AppTheme" parent="android:Theme.Light" /> + +</resources> diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/MainActivity.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/MainActivity.java new file mode 100644 index 0000000..097d15a --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/MainActivity.java @@ -0,0 +1,60 @@ +/* + * 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.testapp; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.view.WindowManager; + +public class MainActivity extends FragmentActivity implements TestListFragment.Callbacks { + + private boolean mTwoPane; + public static final String LOG_TAG = "UiAutomatorApp"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // If the device is locked, this attempts to dismiss the KeyGuard + getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | + WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + setContentView(R.layout.list_activity); + + if (findViewById(R.id.test_detail_container) != null) { + mTwoPane = true; + ((TestListFragment) getSupportFragmentManager().findFragmentById(R.id.item_list)) + .setActivateOnItemClick(true); + } + } + + @Override + public void onItemSelected(String id) { + if (mTwoPane) { + Fragment fragment = TestItems.getFragment(id); + getSupportFragmentManager().beginTransaction() + .replace(R.id.test_detail_container, fragment).commit(); + } else { + Intent detailIntent = new Intent(this, SinglePaneDetailActivity.class); + detailIntent.putExtra("item_id", id); + startActivity(detailIntent); + } + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/SinglePaneDetailActivity.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/SinglePaneDetailActivity.java new file mode 100644 index 0000000..d45ac2b --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/SinglePaneDetailActivity.java @@ -0,0 +1,56 @@ +/* + * 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.testapp; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.NavUtils; +import android.view.Menu; +import android.view.MenuItem; + +public class SinglePaneDetailActivity extends FragmentActivity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.singlepane_activity); + getActionBar().setDisplayHomeAsUpEnabled(true); + + if (savedInstanceState == null) { + Fragment fragment = TestItems.getFragment(getIntent().getStringExtra("item_id")); + getSupportFragmentManager().beginTransaction() + .add(R.id.test_results_detail_container, fragment).commit(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.test_results_detail_activity, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + NavUtils.navigateUpFromSameTask(this); + return true; + } + return super.onOptionsItemSelected(item); + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test1DetailFragment.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test1DetailFragment.java new file mode 100644 index 0000000..e547434 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test1DetailFragment.java @@ -0,0 +1,80 @@ +/* + * 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.testapp; + +import android.app.AlertDialog; +import android.content.Context; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; + +public class Test1DetailFragment extends Fragment { + + public static final String ARG_ITEM_ID = "item_id"; + private Button mSubmitButton; + private EditText mEditText; + TestItems.TestItem mItem; + + public Test1DetailFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments().containsKey(ARG_ITEM_ID)) { + mItem = TestItems.getTest(getArguments().getString(ARG_ITEM_ID)); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { + View rootView = inflater.inflate(R.layout.test1_detail_fragment, container, false); + if (mItem != null) { + ((EditText) rootView.findViewById(R.id.test1TextField)).setText(mItem.mName); + + mSubmitButton = (Button) rootView.findViewById(R.id.test1SubmitButton); + mEditText = (EditText) rootView.findViewById(R.id.test1TextField); + mEditText.setText(""); + mSubmitButton.setOnClickListener(new Button.OnClickListener() { + @Override + public void onClick(View v) { + final String savedInput = mEditText.getText().toString(); + // clear so we won't be confused by the input text in + // validation + mEditText.setText(""); + // close soft keyboard + InputMethodManager imm = (InputMethodManager) getActivity().getSystemService( + Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0); + // display the submitted text + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.item1_dialog_title); + builder.setPositiveButton(R.string.OK, null); + builder.setMessage(savedInput); + AlertDialog diag = builder.create(); + diag.show(); + } + }); + } + return rootView; + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test2DetailFragment.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test2DetailFragment.java new file mode 100644 index 0000000..969a5aa --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test2DetailFragment.java @@ -0,0 +1,153 @@ +/* + * 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.testapp; + +import android.app.AlertDialog; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; + +public class Test2DetailFragment extends Fragment { + public static final String ARG_ITEM_ID = "item_id"; + private Button mButton1, mButton2, mButton3, mDynaButton; + + public Test2DetailFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.test2_detail_activity, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.dialog_title_result); + builder.setMessage(item.getTitle()); + builder.setPositiveButton(R.string.OK, null); + AlertDialog diag = builder.create(); + diag.show(); + return super.onOptionsItemSelected(item); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { + View rootView = inflater.inflate(R.layout.test2_detail_fragment, container, false); + + mButton1 = (Button) rootView.findViewById(R.id.test2button1); + mButton2 = (Button) rootView.findViewById(R.id.test2button2); + mButton3 = (Button) rootView.findViewById(R.id.test2button3); + mDynaButton = (Button) rootView.findViewById(R.id.test2dynaButton); + + mButton1.setOnClickListener(new Button.OnClickListener() { + @Override + public void onClick(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.button1); + AlertDialog diag = builder.create(); + diag.show(); + } + }); + + 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) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.dialog_title_result); + builder.setPositiveButton(R.string.OK, null); + builder.setMessage(R.string.button2); + AlertDialog diag = builder.create(); + diag.show(); + } + }); + + 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) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.dialog_title_result); + builder.setPositiveButton(R.string.OK, null); + builder.setMessage(R.string.button3); + AlertDialog diag = builder.create(); + diag.show(); + } + }); + + 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) { + mDynaButton.setText(R.string.buttonAfter); + mDynaButton.setContentDescription(getString(R.string.buttonAfter)); + } + }); + + return rootView; + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test3DetailFragment.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test3DetailFragment.java new file mode 100644 index 0000000..f90709b --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test3DetailFragment.java @@ -0,0 +1,134 @@ +/* + * 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.testapp; + +import android.app.AlertDialog; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.SystemClock; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +public class Test3DetailFragment extends Fragment { + + public static final String ARG_ITEM_ID = "item_id"; + private TextView mTextClock; + private Button mSubmitButton; + private EditText mEditText; + private long mCurrentTime; + private final Object sync = new Object(); + private boolean mRunCounter = true; + + public Test3DetailFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.test2_detail_activity, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.dialog_title_result); + builder.setMessage(item.getTitle()); + builder.setPositiveButton(R.string.OK, null); + AlertDialog diag = builder.create(); + diag.show(); + return super.onOptionsItemSelected(item); + } + + private final Handler mHandler = new Handler(); + + final Runnable mClockRunnable = new Runnable() { + @Override + public void run() { + // call the activity method that updates the UI + updateClockOnUi(); + } + }; + + private void updateClockOnUi() { + synchronized (sync) { + mTextClock.setText("" + mCurrentTime); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { + View rootView = inflater.inflate(R.layout.test3_detail_fragment, container, false); + mTextClock = (TextView) rootView.findViewById(R.id.test3ClockTextView); + mSubmitButton = (Button) rootView.findViewById(R.id.test3SubmitButton); + mEditText = (EditText) rootView.findViewById(R.id.test3TextField); + mSubmitButton.setOnClickListener(new Button.OnClickListener() { + @Override + public void onClick(View v) { + // close soft keyboard + InputMethodManager imm = (InputMethodManager) getActivity().getSystemService( + Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0); + + // display the submitted text + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.test3_dialog_title); + builder.setPositiveButton(R.string.OK, null); + CharSequence inputText = mEditText.getText(); + if (inputText != null && !inputText.toString().isEmpty()) { + long inputTime = Long.parseLong(inputText.toString()); + builder.setMessage("" + (mCurrentTime - inputTime)); + } else { + builder.setMessage("<NO DATA>"); + } + AlertDialog diag = builder.create(); + diag.show(); + mEditText.setText(""); + mRunCounter = false; + } + }); + + new Thread(new Runnable() { + @Override + public void run() { + while (mRunCounter) { + synchronized (sync) { + mCurrentTime = SystemClock.elapsedRealtime(); + } + mHandler.post(mClockRunnable); + SystemClock.sleep(100); + } + } + }).start(); + + return rootView; + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test4DetailFragment.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test4DetailFragment.java new file mode 100644 index 0000000..ce535c4 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test4DetailFragment.java @@ -0,0 +1,178 @@ +/* + * 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.testapp; + +import android.app.ActionBar; +import android.app.FragmentTransaction; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class Test4DetailFragment extends Fragment implements ActionBar.TabListener { + public static final String ARG_ITEM_ID = "item_id"; + + /** + * The {@link android.support.v4.view.PagerAdapter} that will provide + * fragments for each of the sections. We use a + * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which + * will keep every loaded fragment in memory. If this becomes too memory + * intensive, it may be best to switch to a + * {@link android.support.v4.app.FragmentStatePagerAdapter}. + */ + SectionsPagerAdapter mSectionsPagerAdapter; + + /** + * The {@link ViewPager} that will host the section contents. + */ + ViewPager mViewPager; + + public Test4DetailFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public void onDestroyView() { + getActivity().getActionBar().removeAllTabs(); + super.onDestroyView(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { + + View rootView = inflater.inflate(R.layout.test4_detail_fragment, container, false); + + // Set up the action bar. + final ActionBar actionBar = getActivity().getActionBar(); + if (actionBar.getTabCount() > 0) { + return rootView; + } + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + + // Create the adapter that will return a fragment for each of the three + // primary sections of the app. + mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity().getSupportFragmentManager()); + + // Set up the ViewPager with the sections adapter. + mViewPager = (ViewPager) rootView.findViewById(R.id.test_4_detail_container); + mViewPager.setAdapter(mSectionsPagerAdapter); + + // When swiping between different sections, select the corresponding + // tab. We can also use ActionBar.Tab#select() to do this if we have a + // reference to the Tab. + mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + actionBar.setSelectedNavigationItem(position); + } + }); + + // For each of the sections in the app, add a tab to the action bar. + for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) { + // Create a tab with text corresponding to the page title defined by + // the adapter. Also specify this Activity object, which implements + // the TabListener interface, as the listener for when this tab is + // selected. + actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i)) + .setTabListener(this)); + } + return rootView; + } + + @Override + public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { + } + + @Override + public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { + } + + @Override + public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { + } + + /** + * A {@link FragmentPagerAdapter} that returns a fragment corresponding to + * one of the primary sections of the app. + */ + public class SectionsPagerAdapter extends FragmentPagerAdapter { + + public SectionsPagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int i) { + Fragment fragment = new DummySectionFragment(); + Bundle args = new Bundle(); + args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, i + 1); + fragment.setArguments(args); + return fragment; + } + + @Override + public int getCount() { + return 4; + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return getString(R.string.title_section1).toUpperCase(); + case 1: + return getString(R.string.title_section2).toUpperCase(); + case 2: + return getString(R.string.title_section3).toUpperCase(); + case 3: + return getString(R.string.title_section4).toUpperCase(); + } + return null; + } + } + + /** + * A dummy fragment representing a section of the app, but that simply + * displays dummy text. + */ + public static class DummySectionFragment extends Fragment { + public DummySectionFragment() { + } + + public static final String ARG_SECTION_NUMBER = "section_number"; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + TextView textView = new TextView(getActivity()); + textView.setGravity(Gravity.CENTER); + Bundle args = getArguments(); + textView.setText("[ " + Integer.toString(args.getInt(ARG_SECTION_NUMBER)) + " ]"); + return textView; + } + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test5DetailFragment.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test5DetailFragment.java new file mode 100644 index 0000000..ad22078 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test5DetailFragment.java @@ -0,0 +1,151 @@ +/* + * 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.testapp; + +import android.app.AlertDialog; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.ImageButton; +import android.widget.SeekBar; +import android.widget.Spinner; + +public class Test5DetailFragment extends Fragment { + + public static final String ARG_ITEM_ID = "item_id"; + + class PointerEvent { + int startX; + int startY; + int endX; + int endY; + } + + private final PointerEvent mPointerEvent = new PointerEvent(); + + public Test5DetailFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { + View rootView = inflater.inflate(R.layout.test5_detail_fragment, container, false); + + // Set the content description for the following + Spinner spinner = (Spinner) rootView.findViewById(R.id.test_5_spinner); + spinner.setContentDescription("Spinner"); + ImageButton imageButton = (ImageButton) rootView.findViewById(R.id.test_5_imageButton); + imageButton.setContentDescription("Image button"); + + // Each time this view is displayed, reset the following states + SeekBar seekBar = (SeekBar) rootView.findViewById(R.id.test_5_seekBar); + seekBar.setProgress(50); + seekBar.setContentDescription("Progress is 50 %"); + CheckBox checkbox = (CheckBox) rootView.findViewById(R.id.test_5_checkBox); + checkbox.setChecked(false); + + // Register click event handlers for the following + Button button = (Button) rootView.findViewById(R.id.test_5_button1); + button.setOnClickListener(new Button.OnClickListener() { + @Override + public void onClick(View v) { + // we want an artificial crash + throw new RuntimeException("Artificial crash to test UiWatcher"); + } + }); + + imageButton.setOnTouchListener(new ImageButton.OnTouchListener() { + + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + resetTouchResults(); + collectStartAction(event, v); + } else if (event.getAction() == MotionEvent.ACTION_UP) { + collectEndAction(event, v); + displayTouchResults(); + } + return false; + } + }); + + return rootView; + } + + private void displayTouchResults() { + StringBuilder output = new StringBuilder(); + + output.append(String.format("%d,%d:%d,%d\n", + mPointerEvent.startX, mPointerEvent.startY, mPointerEvent.endX, + mPointerEvent.endY)); + + // display the submitted text + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.drag_item_touch_dialog_title); + builder.setPositiveButton(R.string.OK, null); + builder.setMessage(output.toString()); + AlertDialog diag = builder.create(); + diag.show(); + } + + /** + * Clears all collected pointer results + */ + private void resetTouchResults() { + mPointerEvent.startX = mPointerEvent.startY = + mPointerEvent.endX = mPointerEvent.endY = -1; + } + + /** + * Collects pointer touch information converting from relative to absolute before + * storing it as starting touch coordinates. + * + * @param event + * @param view + * @param pointerIndex + */ + private void collectStartAction(MotionEvent event, View view) { + int offsetInScreen[] = new int[2]; + view.getLocationOnScreen(offsetInScreen); + mPointerEvent.startX = (int)(event.getX() + offsetInScreen[0]); + mPointerEvent.startY = (int)(event.getY() + offsetInScreen[1]); + } + + /** + * Collects pointer touch information converting from relative to absolute before + * storing it as ending touch coordinates. + * + * @param event + * @param view + * @param pointerIndex + */ + private void collectEndAction(MotionEvent event, View view) { + int offsetInScreen[] = new int[2]; + view.getLocationOnScreen(offsetInScreen); + mPointerEvent.endX = (int)(event.getX() + offsetInScreen[0]); + mPointerEvent.endY = (int)(event.getY() + offsetInScreen[1]); + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test6DetailFragment.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test6DetailFragment.java new file mode 100644 index 0000000..ed47734 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/Test6DetailFragment.java @@ -0,0 +1,50 @@ +/* + * 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.testapp; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebView; + +public class Test6DetailFragment extends Fragment { + public static final String ARG_ITEM_ID = "item_id"; + private final static String PAGE = "<html><body>" + + "This is test <b>6</b> for WebView text traversal test." + + "<p/><a href=\"http://google.com\">This is a link to google</a><br/>" + + "<h5>This is h5 text</h5>" + + "<a href=\"http://yahoo.com\">This is a link to yahoo</a>" + + "<p/><h4>This is h4 text</h4>" + "</body></html>"; + + public Test6DetailFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { + View rootView = inflater.inflate(R.layout.test6_detail_fragment, container, false); + WebView wv = (WebView) rootView.findViewById(R.id.test6WebView); + wv.loadData(PAGE, "text/html", null); + return rootView; + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestGenericDetailFragment.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestGenericDetailFragment.java new file mode 100644 index 0000000..6113ca2 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestGenericDetailFragment.java @@ -0,0 +1,176 @@ +/* + * 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.testapp; + +import android.app.AlertDialog; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class TestGenericDetailFragment extends Fragment { + public static final String ARG_ITEM_ID = "item_id"; + TestItems.TestItem mItem; + + private class PointerEvent { + int startX; + int startY; + int endX; + int endY; + } + + private final PointerEvent[] mPointerEvents = new PointerEvent[10]; + + public TestGenericDetailFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments().containsKey(ARG_ITEM_ID)) { + mItem = TestItems.getTest(getArguments().getString(ARG_ITEM_ID)); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { + View rootView = inflater.inflate(R.layout.test_results_detail_fragment, container, false); + if (mItem != null) { + ((TextView) rootView.findViewById(R.id.testResultsTextView)).setText(mItem.mName); + } + + // listen to touch events to verify the multiPointerGesture APIs + // Since API Level 18 + rootView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + + switch(event.getAction() & MotionEvent.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + // Reset any collected touch coordinate results on the primary touch down + resetTouchResults(); + // collect this event + collectStartAction(event, v, 0); + break; + + case MotionEvent.ACTION_POINTER_DOWN: + // collect this event + collectStartAction(event, v, getPointerIndex(event)); + break; + + case MotionEvent.ACTION_POINTER_UP: + // collect this event + collectEndAction(event, v, getPointerIndex(event)); + break; + + case MotionEvent.ACTION_UP: + // collect this event + collectEndAction(event, v, 0); + // on the primary touch up display results collected for all pointers + displayTouchResults(); + break; + } + return true; + } + }); + + return rootView; + } + + /** + * Displays collected results from all pointers into a dialog view in the following + * format: "startX,startY:endX,endY" where each line represent data for a pointer if + * multiple pointers (fingers) were detected. + */ + private void displayTouchResults() { + StringBuilder output = new StringBuilder(); + for (int x = 0; x < mPointerEvents.length; x++) { + if (mPointerEvents[x].startX == -1) + break; + + output.append(String.format("%d,%d:%d,%d\n", + mPointerEvents[x].startX, mPointerEvents[x].startY, mPointerEvents[x].endX, + mPointerEvents[x].endY)); + } + + // display the submitted text + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + builder.setTitle(R.string.generic_item_touch_dialog_title); + builder.setPositiveButton(R.string.OK, null); + builder.setMessage(output.toString()); + AlertDialog diag = builder.create(); + diag.show(); + } + + /** + * Clears all collected pointer results + */ + private void resetTouchResults() { + for (int x = 0; x < mPointerEvents.length; x++) { + if (mPointerEvents[x] == null) + mPointerEvents[x] = new PointerEvent(); + mPointerEvents[x].startX = mPointerEvents[x].startY = + mPointerEvents[x].endX = mPointerEvents[x].endY = -1; + } + } + + /** + * Collects pointer touch information converting from relative to absolute before + * storing it as starting touch coordinates. + * + * @param event + * @param view + * @param pointerIndex + */ + private void collectStartAction(MotionEvent event, View view, int pointerIndex) { + int offsetInScreen[] = new int[2]; + view.getLocationOnScreen(offsetInScreen); + mPointerEvents[getPointerId(event)].startX = + (int)(event.getX(pointerIndex) + offsetInScreen[0]); + mPointerEvents[getPointerId(event)].startY = + (int)(event.getY(pointerIndex) + offsetInScreen[1]); + } + + /** + * Collects pointer touch information converting from relative to absolute before + * storing it as ending touch coordinates. + * + * @param event + * @param view + * @param pointerIndex + */ + private void collectEndAction(MotionEvent event, View view, int pointerIndex) { + int offsetInScreen[] = new int[2]; + view.getLocationOnScreen(offsetInScreen); + mPointerEvents[getPointerId(event)].endX = + (int)(event.getX(pointerIndex) + offsetInScreen[0]); + mPointerEvents[getPointerId(event)].endY = + (int)(event.getY(pointerIndex) + offsetInScreen[1]); + } + + private int getPointerId(MotionEvent event) { + return event.getPointerId(getPointerIndex(event)); + } + + private int getPointerIndex(MotionEvent event) { + return ((event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) + >> MotionEvent.ACTION_POINTER_INDEX_SHIFT); + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestItems.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestItems.java new file mode 100644 index 0000000..59b65f3 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestItems.java @@ -0,0 +1,127 @@ +/* + * 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.testapp; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Log; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class TestItems { + private static String LOG_TAG = TestItems.class.getSimpleName(); + private static List<TestItem> ITEMS = new ArrayList<TestItem>(); + private static Map<String, TestItem> ITEM_MAP = new HashMap<String, TestItem>(); + + public static class TestItem { + public String mId; + public String mName; + private final Class<Fragment> mClassFragment; + public String mTestDescription; + + @SuppressWarnings("unchecked") + public TestItem(String id, String name, Class<?> clsf) { + mId = id; + mName = name; + mClassFragment = (Class<Fragment>) clsf; + } + + @Override + public String toString() { + return mName; + } + } + + static { + addTestItem(new TestItem("1", "Test 1", Test1DetailFragment.class)); + addTestItem(new TestItem("2", "Test 2", Test2DetailFragment.class)); + addTestItem(new TestItem("3", "Test 3", Test3DetailFragment.class)); + addTestItem(new TestItem("4", "Test 4", Test4DetailFragment.class)); + addTestItem(new TestItem("5", "Test 5", Test5DetailFragment.class)); + addTestItem(new TestItem("6", "Test 6", Test6DetailFragment.class)); + addTestItem(new TestItem("7", "Test 7", TestGenericDetailFragment.class)); + addTestItem(new TestItem("8", "Test 8", TestGenericDetailFragment.class)); + addTestItem(new TestItem("9", "Test 9", TestGenericDetailFragment.class)); + addTestItem(new TestItem("10", "Test 10", TestGenericDetailFragment.class)); + addTestItem(new TestItem("11", "Test 11", TestGenericDetailFragment.class)); + addTestItem(new TestItem("12", "Test 12", TestGenericDetailFragment.class)); + addTestItem(new TestItem("13", "Test 13", TestGenericDetailFragment.class)); + addTestItem(new TestItem("14", "Test 14", TestGenericDetailFragment.class)); + addTestItem(new TestItem("15", "Test 15", TestGenericDetailFragment.class)); + addTestItem(new TestItem("16", "Test 16", TestGenericDetailFragment.class)); + addTestItem(new TestItem("17", "Test 17", TestGenericDetailFragment.class)); + addTestItem(new TestItem("18", "Test 18", TestGenericDetailFragment.class)); + addTestItem(new TestItem("19", "Test 19", TestGenericDetailFragment.class)); + addTestItem(new TestItem("20", "Test 20", TestGenericDetailFragment.class)); + addTestItem(new TestItem("21", "Test 21", TestGenericDetailFragment.class)); + addTestItem(new TestItem("22", "Test 22", TestGenericDetailFragment.class)); + addTestItem(new TestItem("23", "Test 23", TestGenericDetailFragment.class)); + addTestItem(new TestItem("24", "Test 24", TestGenericDetailFragment.class)); + addTestItem(new TestItem("25", "Test 25", TestGenericDetailFragment.class)); + addTestItem(new TestItem("26", "Test 26", TestGenericDetailFragment.class)); + addTestItem(new TestItem("27", "Test 27", TestGenericDetailFragment.class)); + addTestItem(new TestItem("28", "Test 28", TestGenericDetailFragment.class)); + addTestItem(new TestItem("29", "Test 29", TestGenericDetailFragment.class)); + addTestItem(new TestItem("30", "Test 30", TestGenericDetailFragment.class)); + addTestItem(new TestItem("31", "Test 31", TestGenericDetailFragment.class)); + addTestItem(new TestItem("32", "Test 32", TestGenericDetailFragment.class)); + addTestItem(new TestItem("33", "Test 33", TestGenericDetailFragment.class)); + addTestItem(new TestItem("34", "Test 34", TestGenericDetailFragment.class)); + addTestItem(new TestItem("35", "Test 35", TestGenericDetailFragment.class)); + addTestItem(new TestItem("36", "Test 36", TestGenericDetailFragment.class)); + addTestItem(new TestItem("37", "Test 37", TestGenericDetailFragment.class)); + addTestItem(new TestItem("38", "Test 38", TestGenericDetailFragment.class)); + addTestItem(new TestItem("39", "Test 39", TestGenericDetailFragment.class)); + addTestItem(new TestItem("40", "Test 40", TestGenericDetailFragment.class)); + } + + private static void addTestItem(TestItem item) { + ITEMS.add(item); + ITEM_MAP.put(item.mId, item); + } + + public static List<TestItem> getTests() { + return ITEMS; + } + + public static TestItem getTest(String id) { + return ITEM_MAP.get(id); + } + + public static TestItem getTest(int pos) { + return ITEMS.get(pos); + } + + public static Fragment getFragment(String id) { + try { + Fragment fragment = getTest(id).mClassFragment.newInstance(); + Bundle arguments = new Bundle(); + arguments.putString("item_id", id); + fragment.setArguments(arguments); + return fragment; + } catch (InstantiationException e) { + Log.e(LOG_TAG, "Exception", e); + return null; + } catch (IllegalAccessException e) { + Log.e(LOG_TAG, "Exception", e); + return null; + } + } +} diff --git a/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestListFragment.java b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestListFragment.java new file mode 100644 index 0000000..f93dd04 --- /dev/null +++ b/tests/CtsUiAutomatorTest/testapp/src/com/android/uiautomator/tests/cts/testapp/TestListFragment.java @@ -0,0 +1,105 @@ +/* + * 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.testapp; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.ListView; + +public class TestListFragment extends ListFragment { + + private static final String STATE_ACTIVATED_POSITION = "activated_position"; + + private Callbacks mCallbacks = sDummyCallbacks; + private int mActivatedPosition = ListView.INVALID_POSITION; + + public interface Callbacks { + + public void onItemSelected(String id); + } + + private static Callbacks sDummyCallbacks = new Callbacks() { + @Override + public void onItemSelected(String id) { + } + }; + + public TestListFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setListAdapter(new ArrayAdapter<TestItems.TestItem>(getActivity(), + R.layout.simple_list_item_selected, R.id.label, TestItems.getTests())); + } + + @Override + public void onViewCreated(View view, Bundle savedState) { + super.onViewCreated(view, savedState); + if (savedState != null && savedState.containsKey(STATE_ACTIVATED_POSITION)) { + setActivatedPosition(savedState.getInt(STATE_ACTIVATED_POSITION)); + } + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (!(activity instanceof Callbacks)) { + throw new IllegalStateException("Activity must implement fragment's callbacks."); + } + + mCallbacks = (Callbacks) activity; + } + + @Override + public void onDetach() { + super.onDetach(); + mCallbacks = sDummyCallbacks; + } + + @Override + public void onListItemClick(ListView listView, View view, int position, long id) { + super.onListItemClick(listView, view, position, id); + mCallbacks.onItemSelected(TestItems.getTest(position).mId); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + if (mActivatedPosition != ListView.INVALID_POSITION) { + outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition); + } + } + + public void setActivateOnItemClick(boolean activateOnItemClick) { + getListView().setChoiceMode( + activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE); + } + + public void setActivatedPosition(int position) { + if (position == ListView.INVALID_POSITION) { + getListView().setItemChecked(mActivatedPosition, false); + } else { + getListView().setItemChecked(position, true); + } + + mActivatedPosition = position; + } +} |