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 androidx.test.filters.LargeTest; 28 import androidx.test.runner.AndroidJUnit4; 29 30 import com.android.launcher3.Launcher; 31 import com.android.launcher3.LauncherState; 32 import com.android.launcher3.popup.ArrowPopup; 33 import com.android.launcher3.tapl.AllApps; 34 import com.android.launcher3.tapl.AppIcon; 35 import com.android.launcher3.tapl.AppIconMenu; 36 import com.android.launcher3.tapl.AppIconMenuItem; 37 import com.android.launcher3.tapl.TestHelpers; 38 import com.android.launcher3.tapl.Widgets; 39 import com.android.launcher3.tapl.Workspace; 40 import com.android.launcher3.views.OptionsPopupView; 41 import com.android.launcher3.widget.WidgetsFullSheet; 42 import com.android.launcher3.widget.WidgetsRecyclerView; 43 44 import org.junit.Before; 45 import org.junit.Ignore; 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 49 @LargeTest 50 @RunWith(AndroidJUnit4.class) 51 public class TaplTestsLauncher3 extends AbstractLauncherUiTest { 52 private static final String APP_NAME = "LauncherTestApp"; 53 54 @Before setUp()55 public void setUp() throws Exception { 56 super.setUp(); 57 initialize(this); 58 } 59 initialize(AbstractLauncherUiTest test)60 public static void initialize(AbstractLauncherUiTest test) throws Exception { 61 test.clearLauncherData(); 62 test.mDevice.pressHome(); 63 test.waitForLauncherCondition("Launcher didn't start", launcher -> launcher != null); 64 test.waitForState("Launcher internal state didn't switch to Home", LauncherState.NORMAL); 65 test.waitForResumed("Launcher internal state is still Background"); 66 // Check that we switched to home. 67 test.mLauncher.getWorkspace(); 68 } 69 70 // Please don't add negative test cases for methods that fail only after a long wait. expectFail(String message, Runnable action)71 public static void expectFail(String message, Runnable action) { 72 boolean failed = false; 73 try { 74 action.run(); 75 } catch (AssertionError e) { 76 failed = true; 77 } 78 assertTrue(message, failed); 79 } 80 isWorkspaceScrollable(Launcher launcher)81 private boolean isWorkspaceScrollable(Launcher launcher) { 82 return launcher.getWorkspace().getPageCount() > 1; 83 } 84 getCurrentWorkspacePage(Launcher launcher)85 private int getCurrentWorkspacePage(Launcher launcher) { 86 return launcher.getWorkspace().getCurrentPage(); 87 } 88 getWidgetsView(Launcher launcher)89 private WidgetsRecyclerView getWidgetsView(Launcher launcher) { 90 return WidgetsFullSheet.getWidgetsView(launcher); 91 } 92 93 @Test testDevicePressMenu()94 public void testDevicePressMenu() throws Exception { 95 mDevice.pressMenu(); 96 mDevice.waitForIdle(); 97 executeOnLauncher( 98 launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu", 99 OptionsPopupView.getOptionsPopup(launcher) != null)); 100 // Check that pressHome works when the menu is shown. 101 mLauncher.pressHome(); 102 } 103 104 @Test 105 @Ignore testPressHomeOnAllAppsContextMenu()106 public void testPressHomeOnAllAppsContextMenu() throws Exception { 107 final AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 108 allApps.freeze(); 109 try { 110 allApps.getAppIcon("TestActivity7").openMenu(); 111 } finally { 112 allApps.unfreeze(); 113 } 114 mLauncher.pressHome(); 115 } 116 runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps)117 public static void runAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { 118 allApps.freeze(); 119 try { 120 assertNotNull("allApps parameter is null", allApps); 121 122 assertTrue( 123 "Launcher internal state is not All Apps", 124 test.isInState(LauncherState.ALL_APPS)); 125 126 // Test flinging forward and backward. 127 test.executeOnLauncher(launcher -> assertEquals( 128 "All Apps started in already scrolled state", 0, 129 test.getAllAppsScroll(launcher))); 130 131 allApps.flingForward(); 132 assertTrue("Launcher internal state is not All Apps", 133 test.isInState(LauncherState.ALL_APPS)); 134 final Integer flingForwardY = test.getFromLauncher( 135 launcher -> test.getAllAppsScroll(launcher)); 136 test.executeOnLauncher( 137 launcher -> assertTrue("flingForward() didn't scroll App Apps", 138 flingForwardY > 0)); 139 140 allApps.flingBackward(); 141 assertTrue( 142 "Launcher internal state is not All Apps", 143 test.isInState(LauncherState.ALL_APPS)); 144 final Integer flingBackwardY = test.getFromLauncher( 145 launcher -> test.getAllAppsScroll(launcher)); 146 test.executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps", 147 flingBackwardY < flingForwardY)); 148 149 // Test scrolling down to YouTube. 150 assertNotNull("All apps: can't fine YouTube", allApps.getAppIcon("YouTube")); 151 // Test scrolling up to Camera. 152 assertNotNull("All apps: can't fine Camera", allApps.getAppIcon("Camera")); 153 // Test failing to find a non-existing app. 154 final AllApps allAppsFinal = allApps; 155 expectFail("All apps: could find a non-existing app", 156 () -> allAppsFinal.getAppIcon("NO APP")); 157 158 assertTrue( 159 "Launcher internal state is not All Apps", 160 test.isInState(LauncherState.ALL_APPS)); 161 } finally { 162 allApps.unfreeze(); 163 } 164 } 165 166 @Test 167 @PortraitLandscape testWorkspaceSwitchToAllApps()168 public void testWorkspaceSwitchToAllApps() { 169 assertNotNull("switchToAllApps() returned null", 170 mLauncher.getWorkspace().switchToAllApps()); 171 assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); 172 } 173 174 @Test testWorkspace()175 public void testWorkspace() throws Exception { 176 final Workspace workspace = mLauncher.getWorkspace(); 177 178 // Test that ensureWorkspaceIsScrollable adds a page by dragging an icon there. 179 executeOnLauncher(launcher -> assertFalse("Initial workspace state is scrollable", 180 isWorkspaceScrollable(launcher))); 181 assertNull("Chrome app was found on empty workspace", 182 workspace.tryGetWorkspaceAppIcon("Chrome")); 183 184 workspace.ensureWorkspaceIsScrollable(); 185 186 executeOnLauncher( 187 launcher -> assertEquals("Ensuring workspace scrollable didn't switch to page #1", 188 1, getCurrentWorkspacePage(launcher))); 189 executeOnLauncher( 190 launcher -> assertTrue("ensureScrollable didn't make workspace scrollable", 191 isWorkspaceScrollable(launcher))); 192 assertNotNull("ensureScrollable didn't add Chrome app", 193 workspace.tryGetWorkspaceAppIcon("Chrome")); 194 195 // Test flinging workspace. 196 workspace.flingBackward(); 197 assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL)); 198 executeOnLauncher( 199 launcher -> assertEquals("Flinging back didn't switch workspace to page #0", 200 0, getCurrentWorkspacePage(launcher))); 201 202 workspace.flingForward(); 203 executeOnLauncher( 204 launcher -> assertEquals("Flinging forward didn't switch workspace to page #1", 205 1, getCurrentWorkspacePage(launcher))); 206 assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL)); 207 208 // Test starting a workspace app. 209 final AppIcon app = workspace.tryGetWorkspaceAppIcon("Chrome"); 210 assertNotNull("No Chrome app in workspace", app); 211 } 212 runIconLaunchFromAllAppsTest(AbstractLauncherUiTest test, AllApps allApps)213 public static void runIconLaunchFromAllAppsTest(AbstractLauncherUiTest test, AllApps allApps) { 214 allApps.freeze(); 215 try { 216 final AppIcon app = allApps.getAppIcon("TestActivity7"); 217 assertNotNull("AppIcon.launch returned null", app.launch(getAppPackageName())); 218 test.executeOnLauncher(launcher -> assertTrue( 219 "Launcher activity is the top activity; expecting another activity to be the top " 220 + "one", 221 test.isInBackground(launcher))); 222 } finally { 223 allApps.unfreeze(); 224 } 225 } 226 227 @Test 228 @PortraitLandscape testAppIconLaunchFromAllAppsFromHome()229 public void testAppIconLaunchFromAllAppsFromHome() throws Exception { 230 final AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); 231 assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); 232 233 runIconLaunchFromAllAppsTest(this, allApps); 234 } 235 236 @Test 237 @PortraitLandscape testWidgets()238 public void testWidgets() throws Exception { 239 // Test opening widgets. 240 executeOnLauncher(launcher -> 241 assertTrue("Widgets is initially opened", getWidgetsView(launcher) == null)); 242 Widgets widgets = mLauncher.getWorkspace().openAllWidgets(); 243 assertNotNull("openAllWidgets() returned null", widgets); 244 widgets = mLauncher.getAllWidgets(); 245 assertNotNull("getAllWidgets() returned null", widgets); 246 executeOnLauncher(launcher -> 247 assertTrue("Widgets is not shown", getWidgetsView(launcher).isShown())); 248 executeOnLauncher(launcher -> assertEquals("Widgets is scrolled upon opening", 249 0, getWidgetsScroll(launcher))); 250 251 // Test flinging widgets. 252 widgets.flingForward(); 253 Integer flingForwardY = getFromLauncher(launcher -> getWidgetsScroll(launcher)); 254 executeOnLauncher(launcher -> assertTrue("Flinging forward didn't scroll widgets", 255 flingForwardY > 0)); 256 257 widgets.flingBackward(); 258 executeOnLauncher(launcher -> assertTrue("Flinging backward didn't scroll widgets", 259 getWidgetsScroll(launcher) < flingForwardY)); 260 261 mLauncher.pressHome(); 262 waitForLauncherCondition("Widgets were not closed", 263 launcher -> getWidgetsView(launcher) == null); 264 } 265 getWidgetsScroll(Launcher launcher)266 private int getWidgetsScroll(Launcher launcher) { 267 return getWidgetsView(launcher).getCurrentScrollY(); 268 } 269 isOptionsPopupVisible(Launcher launcher)270 private boolean isOptionsPopupVisible(Launcher launcher) { 271 final ArrowPopup popup = OptionsPopupView.getOptionsPopup(launcher); 272 return popup != null && popup.isShown(); 273 } 274 275 @Test 276 @PortraitLandscape testLaunchMenuItem()277 public void testLaunchMenuItem() throws Exception { 278 final AllApps allApps = mLauncher. 279 getWorkspace(). 280 switchToAllApps(); 281 allApps.freeze(); 282 try { 283 final AppIconMenu menu = allApps. 284 getAppIcon(APP_NAME). 285 openMenu(); 286 287 executeOnLauncher( 288 launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu", 289 isOptionsPopupVisible(launcher))); 290 291 menu.getMenuItem(1).launch(getAppPackageName()); 292 } finally { 293 allApps.unfreeze(); 294 } 295 } 296 297 @Test 298 @PortraitLandscape testDragAppIcon()299 public void testDragAppIcon() throws Throwable { 300 // 1. Open all apps and wait for load complete. 301 // 2. Drag icon to homescreen. 302 // 3. Verify that the icon works on homescreen. 303 final AllApps allApps = mLauncher.getWorkspace(). 304 switchToAllApps(); 305 allApps.freeze(); 306 try { 307 allApps. 308 getAppIcon(APP_NAME). 309 dragToWorkspace(). 310 getWorkspaceAppIcon(APP_NAME). 311 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 // 4. Drag the first shortcut to the home screen. 339 // 5. Verify that the shortcut works on home screen 340 // (the app opens and has the same text as the shortcut). 341 menuItem. 342 dragToWorkspace(). 343 getWorkspaceAppIcon(shortcutName). 344 launch(getAppPackageName()); 345 } finally { 346 allApps.unfreeze(); 347 } 348 } 349 getAppPackageName()350 public static String getAppPackageName() { 351 return getInstrumentation().getContext().getPackageName(); 352 } 353 } 354