OSDN Git Service

Add UI tests for new time zone picker
authorVictor Chang <vichang@google.com>
Mon, 22 Jan 2018 19:27:17 +0000 (19:27 +0000)
committerVictor Chang <vichang@google.com>
Mon, 29 Jan 2018 23:33:04 +0000 (23:33 +0000)
- Test selecting 2 time zones in picker
- Device.wait could return null object and cause NPE.
  Add helper function throw UiObjectNotFoundException with selector info

Bug: 62255208
Test: atest SettingsUITests:ZonePickerSettingsTest
Change-Id: Id0439dde25240cf2d3ee834043d1726a2c738d1a

tests/uitests/src/com/android/settings/ui/ZonePickerSettingsTest.java [new file with mode: 0644]

diff --git a/tests/uitests/src/com/android/settings/ui/ZonePickerSettingsTest.java b/tests/uitests/src/com/android/settings/ui/ZonePickerSettingsTest.java
new file mode 100644 (file)
index 0000000..109c3bc
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiScrollable;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.SettingsHelper;
+import android.system.helpers.SettingsHelper.SettingsType;
+import android.widget.ListView;
+import android.widget.Spinner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.TimeZone;
+
+import static com.android.settings.ui.testutils.SettingsTestUtils.SETTINGS_PACKAGE;
+import static com.android.settings.ui.testutils.SettingsTestUtils.TIMEOUT;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class ZonePickerSettingsTest {
+
+    private static final BySelector SELECTOR_SELECT_TIME_ZONE =
+            By.hasChild(By.text("Select time zone"));
+
+    private UiDevice mDevice;
+    private SettingsHelper mHelper;
+    private String mIsV2EnabledByDefault;
+    private int mIsAutoZoneEnabled;
+
+    @Before
+    public void setUp() throws Exception {
+        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mHelper = SettingsHelper.getInstance();
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientation", e);
+        }
+        mIsV2EnabledByDefault = mHelper.getStringSetting(SettingsType.GLOBAL,
+                "settings_zone_picker_v2");
+        mHelper.setStringSetting(SettingsType.GLOBAL, "settings_zone_picker_v2", "true");
+        mIsAutoZoneEnabled = mHelper.getIntSetting(SettingsType.GLOBAL,
+                Settings.Global.AUTO_TIME_ZONE);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        // Go back to home for next test.
+        mDevice.pressBack();
+        mDevice.pressBack();
+        mDevice.pressHome();
+        mDevice.waitForIdle(TIMEOUT * 2);
+        mHelper.setStringSetting(SettingsType.GLOBAL, "settings_zone_picker_v2",
+                mIsV2EnabledByDefault);
+        mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE,
+                mIsAutoZoneEnabled);
+    }
+
+    @Test
+    public void zonePickerDisabled() throws Exception {
+        mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, 1);
+
+        SettingsHelper.launchSettingsPage(
+                InstrumentationRegistry.getContext(), Settings.ACTION_DATE_SETTINGS);
+        UiObject2 selectTimeZone = wait(SELECTOR_SELECT_TIME_ZONE);
+        assertFalse(selectTimeZone.isEnabled());
+    }
+
+    // Test 2 time zones with no DST
+    @Test
+    public void testSelectReykjavik() throws Exception {
+        testSelectTimeZone("Iceland", "Reykjavik", "GMT+00:00", "Atlantic/Reykjavik");
+    }
+
+    @Test
+    public void testSelectPhoenix() throws Exception {
+        testSelectTimeZone("United States", "Phoenix", "GMT-07:00", "America/Phoenix");
+    }
+
+    private void testSelectTimeZone(String region, String timezone, String expectedTimeZoneOffset,
+            String expectedTimeZoneId) throws Exception {
+        mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, 0);
+
+        SettingsHelper.launchSettingsPage(
+                InstrumentationRegistry.getContext(), Settings.ACTION_DATE_SETTINGS);
+
+        UiObject2 selectTimeZone = wait(SELECTOR_SELECT_TIME_ZONE);
+        assertTrue(selectTimeZone.isEnabled());
+        selectTimeZone.click();
+
+        // Select region in the dropdown list
+        selectScrollableItem(selectDropDownInSpinner(By.clazz(Spinner.class)),
+                new UiSelector().textContains(region))
+                .click();
+
+        // Select time zone
+        selectScrollableItem(selectTimeZoneList(),
+                new UiSelector().textContains(timezone))
+                .click();
+
+        // The select button should include the GMT offset in the summary
+        BySelector summarySelector = By.res("android:id/summary");
+        UiObject2 selectedTimeZone = selectTimeZone.findObject(summarySelector);
+        assertUiObjectFound(selectedTimeZone, summarySelector);
+        assertTrue("Expect " + expectedTimeZoneOffset + " is shown for " + timezone,
+                selectedTimeZone.getText().startsWith(expectedTimeZoneOffset));
+
+        waitAndAssertTimeGetDefault(expectedTimeZoneId);
+        assertEquals("Time zone change in Settings should update persist.sys.timezone",
+                expectedTimeZoneId, SystemProperties.get("persist.sys.timezone"));
+    }
+
+    private static final long CHECK_DEFAULT_TIMEZONE_INTERVAL = 200L;
+    private static final long CHECK_DEFAULT_TIMEZONE_TIMEOUT = 3000L;
+
+    /**
+     * Wait for the broadcast ACTION_TIMEZONE_CHANGED propagated, and update the default TimeZone
+     * by ApplicationThread.
+     */
+    private static void waitAndAssertTimeGetDefault(String expectedTimeZoneId)
+            throws InterruptedException {
+        for (int i = 0; i < CHECK_DEFAULT_TIMEZONE_TIMEOUT / CHECK_DEFAULT_TIMEZONE_INTERVAL; i++) {
+            if (expectedTimeZoneId.equals(TimeZone.getDefault().getID())) {
+                return;
+            }
+            Thread.sleep(CHECK_DEFAULT_TIMEZONE_INTERVAL);
+        }
+
+        assertEquals(expectedTimeZoneId, TimeZone.getDefault().getID());
+    }
+
+    /**
+     * Perform click on {@link Spinner} and return the pop-up dropdown list.
+     * @return UiScrollable representing the pop-up dropdown after clicking on the spinner
+     */
+    private UiScrollable selectDropDownInSpinner(BySelector spinnerSelector)
+            throws UiObjectNotFoundException {
+        UiObject2 spinner = wait(spinnerSelector);
+        spinner.click();
+
+        UiSelector dropDownSelector = new UiSelector().className(ListView.class);
+        return new UiScrollable(dropDownSelector);
+    }
+
+    private UiScrollable selectTimeZoneList() {
+        return new UiScrollable(new UiSelector().resourceId(SETTINGS_PACKAGE + ":id/tz_list"));
+    }
+
+    /**
+     * Select the child object in the UiScrollable
+     * @throws UiObjectNotFoundException if scrollable or child is not found
+     */
+    private UiObject selectScrollableItem(UiScrollable scrollable, UiSelector childSelector)
+            throws UiObjectNotFoundException {
+        if (!scrollable.waitForExists(TIMEOUT)) {
+            throw newUiObjectNotFoundException(scrollable.getSelector());
+        }
+        scrollable.scrollIntoView(childSelector);
+
+        UiObject child = mDevice.findObject(childSelector);
+        assertUiObjectFound(child, childSelector);
+        return child;
+    }
+
+    /**
+     * @throws UiObjectNotFoundException if UiDevice.wait returns null
+     */
+    private UiObject2 wait(BySelector selector) throws UiObjectNotFoundException {
+        UiObject2 item = mDevice.wait(Until.findObject(selector), TIMEOUT);
+        assertUiObjectFound(item, selector);
+        return item;
+    }
+
+    private static void assertUiObjectFound(UiObject2 obj, BySelector selector)
+            throws UiObjectNotFoundException {
+        if (obj == null) {
+            throw newUiObjectNotFoundException(selector);
+        }
+    }
+
+
+    private static void assertUiObjectFound(UiObject obj, UiSelector selector)
+            throws UiObjectNotFoundException {
+        if (obj == null) {
+            throw newUiObjectNotFoundException(selector);
+        }
+    }
+
+    private static UiObjectNotFoundException newUiObjectNotFoundException(Object selector) {
+        return new UiObjectNotFoundException(
+                String.format("UI object not found: %s", selector.toString()));
+    }
+}