1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.ui; 18 19 import static androidx.test.InstrumentationRegistry.getInstrumentation; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertNull; 25 import static org.junit.Assert.assertTrue; 26 27 import android.util.Log; 28 29 import androidx.test.filters.LargeTest; 30 import androidx.test.runner.AndroidJUnit4; 31 32 import com.android.launcher3.Launcher; 33 import com.android.launcher3.LauncherState; 34 import com.android.launcher3.popup.ArrowPopup; 35 import com.android.launcher3.tapl.AllApps; 36 import com.android.launcher3.tapl.AppIcon; 37 import com.android.launcher3.tapl.AppIconMenu; 38 import com.android.launcher3.tapl.AppIconMenuItem; 39 import com.android.launcher3.tapl.Widgets; 40 import com.android.launcher3.tapl.Workspace; 41 import com.android.launcher3.util.rule.TestStabilityRule.Stability; 42 import com.android.launcher3.views.OptionsPopupView; 43 import com.android.launcher3.widget.WidgetsFullSheet; 44 import com.android.launcher3.widget.WidgetsRecyclerView; 45 46 import org.junit.Before; 47 import org.junit.Ignore; 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 51 @LargeTest 52 @RunWith(AndroidJUnit4.class) 53 public class TaplTestsLauncher3 extends AbstractLauncherUiTest { 54 private static final String APP_NAME = "LauncherTestApp"; 55 56 @Before setUp()57 public void setUp() throws Exception { 58 super.setUp(); 59 initialize(this); 60 } 61 initialize(AbstractLauncherUiTest test)62 public static void initialize(AbstractLauncherUiTest test) throws Exception { 63 test.clearLauncherData(); 64 test.mDevice.pressHome(); 65 test.waitForLauncherCondition("Launcher didn't start", launcher -> launcher != null); 66 test.waitForState("Launcher internal state didn't switch to Home", LauncherState.NORMAL); 67 test.waitForResumed("Launcher internal state is still Background"); 68 // Check that we switched to home. 69 test.mLauncher.getWorkspace(); 70 } 71 72 // Please don't add negative test cases for methods that fail only after a long wait. expectFail(String message, Runnable action)73 public static void expectFail(String message, Runnable action) { 74 boolean failed = false; 75 try { 76 action.run(); 77 } catch (AssertionError e) { 78 failed = true; 79 } 80 assertTrue(message, failed); 81 } 82 isWorkspaceScrollable(Launcher launcher)83 private boolean isWorkspaceScrollable(Launcher launcher) { 84 return launcher.getWorkspace().getPageCount() > 1; 85 } 86 getCurrentWorkspacePage(Launcher launcher)87 private int getCurrentWorkspacePage(Launcher launcher) { 88 return launcher.getWorkspace().getCurrentPage(); 89 } 90 getWidgetsView(Launcher launcher)91 private WidgetsRecyclerView getWidgetsView(Launcher launcher) { 92 return WidgetsFullSheet.getWidgetsView(launcher); 93 } 94 95 @Test testDevicePressMenu()96 public void testDevicePressMenu() throws Exception { 97 mDevice.pressMenu(); 98 mDevice.waitForIdle(); 99 executeOnLauncher( 100 launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu", 101 OptionsPopupView.getOptionsPopup(launcher) != null)); 102 // Check that pressHome works when the menu is shown. 103 mLauncher.pressHome(); 104 } 105 106 @Test 107 @Ignore testPressHomeOnAllAppsContextMenu()108 public void testPressHomeOnAllAppsContextMenu() throws Exception { 109 final AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 110 allApps.freeze(); 111 try { 112 allApps.getAppIcon("TestActivity7").openMenu(); 113 } finally { 114 allApps.unfreeze(); 115 } 116 mLauncher.pressHome(); 117 } 118 runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps)119 public static void runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { 120 allApps.freeze(); 121 try { 122 assertNotNull("allApps parameter is null", allApps); 123 124 assertTrue( 125 "Launcher internal state is not All Apps", 126 test.isInState(LauncherState.ALL_APPS)); 127 128 // Test flinging forward and backward. 129 test.executeOnLauncher(launcher -> assertEquals( 130 "All Apps started in already scrolled state", 0, 131 test.getAllAppsScroll(launcher))); 132 133 allApps.flingForward(); 134 assertTrue("Launcher internal state is not All Apps", 135 test.isInState(LauncherState.ALL_APPS)); 136 final Integer flingForwardY = test.getFromLauncher( 137 launcher -> test.getAllAppsScroll(launcher)); 138 test.executeOnLauncher( 139 launcher -> assertTrue("flingForward() didn't scroll App Apps", 140 flingForwardY > 0)); 141 142 allApps.flingBackward(); 143 assertTrue( 144 "Launcher internal state is not All Apps", 145 test.isInState(LauncherState.ALL_APPS)); 146 final Integer flingBackwardY = test.getFromLauncher( 147 launcher -> test.getAllAppsScroll(launcher)); 148 test.executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps", 149 flingBackwardY < flingForwardY)); 150 151 // Test scrolling down to YouTube. 152 assertNotNull("All apps: can't fine YouTube", allApps.getAppIcon("YouTube")); 153 // Test scrolling up to Camera. 154 assertNotNull("All apps: can't fine Camera", allApps.getAppIcon("Camera")); 155 // Test failing to find a non-existing app. 156 final AllApps allAppsFinal = allApps; 157 expectFail("All apps: could find a non-existing app", 158 () -> allAppsFinal.getAppIcon("NO APP")); 159 160 assertTrue( 161 "Launcher internal state is not All Apps", 162 test.isInState(LauncherState.ALL_APPS)); 163 } finally { 164 allApps.unfreeze(); 165 } 166 } 167 168 @Test 169 @PortraitLandscape testWorkspaceSwitchToAllApps()170 public void testWorkspaceSwitchToAllApps() { 171 assertNotNull("switchToAllApps() returned null", 172 mLauncher.getWorkspace().switchToAllApps()); 173 assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); 174 } 175 176 @Test testWorkspace()177 public void testWorkspace() throws Exception { 178 final Workspace workspace = mLauncher.getWorkspace(); 179 180 // Test that ensureWorkspaceIsScrollable adds a page by dragging an icon there. 181 executeOnLauncher(launcher -> assertFalse("Initial workspace state is scrollable", 182 isWorkspaceScrollable(launcher))); 183 assertNull("Chrome app was found on empty workspace", 184 workspace.tryGetWorkspaceAppIcon("Chrome")); 185 186 workspace.ensureWorkspaceIsScrollable(); 187 188 executeOnLauncher( 189 launcher -> assertEquals("Ensuring workspace scrollable didn't switch to page #1", 190 1, getCurrentWorkspacePage(launcher))); 191 executeOnLauncher( 192 launcher -> assertTrue("ensureScrollable didn't make workspace scrollable", 193 isWorkspaceScrollable(launcher))); 194 assertNotNull("ensureScrollable didn't add Chrome app", 195 workspace.getWorkspaceAppIcon("Chrome")); 196 197 // Test flinging workspace. 198 workspace.flingBackward(); 199 assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL)); 200 executeOnLauncher( 201 launcher -> assertEquals("Flinging back didn't switch workspace to page #0", 202 0, getCurrentWorkspacePage(launcher))); 203 204 workspace.flingForward(); 205 executeOnLauncher( 206 launcher -> assertEquals("Flinging forward didn't switch workspace to page #1", 207 1, getCurrentWorkspacePage(launcher))); 208 assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL)); 209 210 // Test starting a workspace app. 211 final AppIcon app = workspace.getWorkspaceAppIcon("Chrome"); 212 assertNotNull("No Chrome app in workspace", app); 213 } 214 runIconLaunchFromAllAppsTest(AbstractLauncherUiTest test, AllApps allApps)215 public static void runIconLaunchFromAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { 216 allApps.freeze(); 217 try { 218 final AppIcon app = allApps.getAppIcon("TestActivity7"); 219 assertNotNull("AppIcon.launch returned null", app.launch(getAppPackageName())); 220 test.executeOnLauncher(launcher -> assertTrue( 221 "Launcher activity is the top activity; expecting another activity to be the " 222 + "top " 223 + "one", 224 test.isInBackground(launcher))); 225 } finally { 226 allApps.unfreeze(); 227 } 228 } 229 230 @Test 231 @PortraitLandscape testAppIconLaunchFromAllAppsFromHome()232 public void testAppIconLaunchFromAllAppsFromHome() throws Exception { 233 final AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 234 assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); 235 236 runIconLaunchFromAllAppsTest(this, allApps); 237 } 238 239 @Test 240 @PortraitLandscape testWidgets()241 public void testWidgets() throws Exception { 242 // Test opening widgets. 243 executeOnLauncher(launcher -> 244 assertTrue("Widgets is initially opened", getWidgetsView(launcher) == null)); 245 Widgets widgets = mLauncher.getWorkspace().openAllWidgets(); 246 assertNotNull("openAllWidgets() returned null", widgets); 247 widgets = mLauncher.getAllWidgets(); 248 assertNotNull("getAllWidgets() returned null", widgets); 249 executeOnLauncher(launcher -> 250 assertTrue("Widgets is not shown", getWidgetsView(launcher).isShown())); 251 executeOnLauncher(launcher -> assertEquals("Widgets is scrolled upon opening", 252 0, getWidgetsScroll(launcher))); 253 254 // Test flinging widgets. 255 widgets.flingForward(); 256 Integer flingForwardY = getFromLauncher(launcher -> getWidgetsScroll(launcher)); 257 executeOnLauncher(launcher -> assertTrue("Flinging forward didn't scroll widgets", 258 flingForwardY > 0)); 259 260 widgets.flingBackward(); 261 executeOnLauncher(launcher -> assertTrue("Flinging backward didn't scroll widgets", 262 getWidgetsScroll(launcher) < flingForwardY)); 263 264 mLauncher.pressHome(); 265 waitForLauncherCondition("Widgets were not closed", 266 launcher -> getWidgetsView(launcher) == null); 267 } 268 getWidgetsScroll(Launcher launcher)269 private int getWidgetsScroll(Launcher launcher) { 270 return getWidgetsView(launcher).getCurrentScrollY(); 271 } 272 isOptionsPopupVisible(Launcher launcher)273 private boolean isOptionsPopupVisible(Launcher launcher) { 274 final ArrowPopup popup = OptionsPopupView.getOptionsPopup(launcher); 275 return popup != null && popup.isShown(); 276 } 277 278 @Test 279 @PortraitLandscape testLaunchMenuItem()280 public void testLaunchMenuItem() throws Exception { 281 final AllApps allApps = mLauncher. 282 getWorkspace(). 283 switchToAllApps(); 284 allApps.freeze(); 285 try { 286 final AppIconMenu menu = allApps. 287 getAppIcon(APP_NAME). 288 openMenu(); 289 290 executeOnLauncher( 291 launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu", 292 isOptionsPopupVisible(launcher))); 293 294 menu.getMenuItem(1).launch(getAppPackageName()); 295 } finally { 296 allApps.unfreeze(); 297 } 298 } 299 300 @Test 301 @PortraitLandscape testDragAppIcon()302 public void testDragAppIcon() throws Throwable { 303 // 1. Open all apps and wait for load complete. 304 // 2. Drag icon to homescreen. 305 // 3. Verify that the icon works on homescreen. 306 final AllApps allApps = mLauncher.getWorkspace(). 307 switchToAllApps(); 308 allApps.freeze(); 309 try { 310 allApps.getAppIcon(APP_NAME).dragToWorkspace(); 311 mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName()); 312 } finally { 313 allApps.unfreeze(); 314 } 315 executeOnLauncher(launcher -> assertTrue( 316 "Launcher activity is the top activity; expecting another activity to be the top " 317 + "one", 318 isInBackground(launcher))); 319 } 320 321 @Test 322 @PortraitLandscape testDragShortcut()323 public void testDragShortcut() throws Throwable { 324 // 1. Open all apps and wait for load complete. 325 // 2. Find the app and long press it to show shortcuts. 326 // 3. Press icon center until shortcuts appear 327 final AllApps allApps = mLauncher. 328 getWorkspace(). 329 switchToAllApps(); 330 allApps.freeze(); 331 try { 332 final AppIconMenuItem menuItem = allApps. 333 getAppIcon(APP_NAME). 334 openMenu(). 335 getMenuItem(0); 336 final String shortcutName = menuItem.getText(); 337 338 menuItem.dragToWorkspace(); 339 mLauncher.getWorkspace().getWorkspaceAppIcon(shortcutName).launch(getAppPackageName()); 340 } finally { 341 allApps.unfreeze(); 342 } 343 } 344 getAppPackageName()345 public static String getAppPackageName() { 346 return getInstrumentation().getContext().getPackageName(); 347 } 348 349 @Test 350 @Stability testTestStabilityAttribute()351 public void testTestStabilityAttribute() { 352 Log.d("TestStabilityRule", "Hello world!"); 353 } 354 } 355