summaryrefslogtreecommitdiff
path: root/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java')
-rw-r--r--tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java311
1 files changed, 311 insertions, 0 deletions
diff --git a/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java b/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java
new file mode 100644
index 0000000000..8bdcd033f7
--- /dev/null
+++ b/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2022 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.launcher3.celllayout;
+
+import static android.platform.uiautomator_helpers.DeviceHelpers.getContext;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.graphics.Point;
+import android.net.Uri;
+import android.util.Log;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.MultipageCellLayout;
+import com.android.launcher3.celllayout.board.CellLayoutBoard;
+import com.android.launcher3.celllayout.board.TestWorkspaceBuilder;
+import com.android.launcher3.celllayout.board.WidgetRect;
+import com.android.launcher3.tapl.Widget;
+import com.android.launcher3.tapl.WidgetResizeFrame;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.util.ModelTestExtensions;
+import com.android.launcher3.util.rule.ShellCommandRule;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TaplReorderWidgetsTest extends AbstractLauncherUiTest {
+
+ @Rule
+ public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
+
+ private static final String TAG = TaplReorderWidgetsTest.class.getSimpleName();
+
+ private static final List<String> FOLDABLE_GRIDS = List.of("normal", "practical", "reasonable");
+
+ TestWorkspaceBuilder mWorkspaceBuilder;
+
+ @Before
+ public void setup() throws Throwable {
+ mWorkspaceBuilder = new TestWorkspaceBuilder(mTargetContext);
+ AbstractLauncherUiTest.initialize(this);
+ }
+
+ @After
+ public void tearDown() {
+ ModelTestExtensions.INSTANCE.clearModelDb(
+ LauncherAppState.getInstance(getContext()).getModel()
+ );
+ }
+
+ /**
+ * Validate if the given board represent the current CellLayout
+ **/
+ private boolean validateBoard(List<CellLayoutBoard> testBoards) {
+ ArrayList<CellLayoutBoard> workspaceBoards = workspaceToBoards();
+ if (workspaceBoards.size() < testBoards.size()) {
+ return false;
+ }
+ for (int i = 0; i < testBoards.size(); i++) {
+ if (testBoards.get(i).compareTo(workspaceBoards.get(i)) != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private FavoriteItemsTransaction buildWorkspaceFromBoards(List<CellLayoutBoard> boards,
+ FavoriteItemsTransaction transaction) {
+ for (int i = 0; i < boards.size(); i++) {
+ CellLayoutBoard board = boards.get(i);
+ mWorkspaceBuilder.buildFromBoard(board, transaction, i);
+ }
+ return transaction;
+ }
+
+ private void printCurrentWorkspace() {
+ InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mTargetContext);
+ ArrayList<CellLayoutBoard> boards = workspaceToBoards();
+ for (int i = 0; i < boards.size(); i++) {
+ Log.d(TAG, "Screen number " + i);
+ Log.d(TAG, ".\n" + boards.get(i).toString(idp.numColumns, idp.numRows));
+ }
+ }
+
+ private ArrayList<CellLayoutBoard> workspaceToBoards() {
+ return getFromLauncher(CellLayoutTestUtils::workspaceToBoards);
+ }
+
+ private WidgetRect getWidgetClosestTo(Point point) {
+ ArrayList<CellLayoutBoard> workspaceBoards = workspaceToBoards();
+ int maxDistance = 9999;
+ WidgetRect bestRect = null;
+ for (int i = 0; i < workspaceBoards.get(0).getWidgets().size(); i++) {
+ WidgetRect widget = workspaceBoards.get(0).getWidgets().get(i);
+ if (widget.getCellX() == 0 && widget.getCellY() == 0) {
+ continue;
+ }
+ int distance = Math.abs(point.x - widget.getCellX())
+ + Math.abs(point.y - widget.getCellY());
+ if (distance == 0) {
+ break;
+ }
+ if (distance < maxDistance) {
+ maxDistance = distance;
+ bestRect = widget;
+ }
+ }
+ return bestRect;
+ }
+
+ /**
+ * This function might be odd, its function is to select a widget and leave it in its place.
+ * The idea is to make the test broader and also test after a widgets resized because the
+ * underlying code does different things in that case
+ */
+ private void triggerWidgetResize(ReorderTestCase testCase) {
+ WidgetRect widgetRect = getWidgetClosestTo(testCase.moveMainTo);
+ if (widgetRect == null) {
+ // Some test doesn't have a widget in the final position, in those cases we will ignore
+ // them
+ return;
+ }
+ Widget widget = mLauncher.getWorkspace().getWidgetAtCell(widgetRect.getCellX(),
+ widgetRect.getCellY());
+ WidgetResizeFrame resizeFrame = widget.dragWidgetToWorkspace(widgetRect.getCellX(),
+ widgetRect.getCellY(), widgetRect.getSpanX(), widgetRect.getSpanY());
+ resizeFrame.dismiss();
+ }
+
+ private void runTestCase(ReorderTestCase testCase) {
+ WidgetRect mainWidgetCellPos = CellLayoutBoard.getMainFromList(
+ testCase.mStart);
+
+ FavoriteItemsTransaction transaction =
+ new FavoriteItemsTransaction(mTargetContext);
+ transaction = buildWorkspaceFromBoards(testCase.mStart, transaction);
+ transaction.commit();
+ mLauncher.waitForLauncherInitialized();
+ // resetLoaderState triggers the launcher to start loading the workspace which allows
+ // waitForLauncherCondition to wait for that condition, otherwise the condition would
+ // always be true and it wouldn't wait for the changes to be applied.
+ waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
+
+ triggerWidgetResize(testCase);
+
+ Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.getCellX(),
+ mainWidgetCellPos.getCellY());
+ assertNotNull(widget);
+ WidgetResizeFrame resizeFrame = widget.dragWidgetToWorkspace(testCase.moveMainTo.x,
+ testCase.moveMainTo.y, mainWidgetCellPos.getSpanX(), mainWidgetCellPos.getSpanY());
+ resizeFrame.dismiss();
+
+ boolean isValid = false;
+ for (List<CellLayoutBoard> boards : testCase.mEnd) {
+ isValid |= validateBoard(boards);
+ if (isValid) break;
+ }
+ printCurrentWorkspace();
+ assertTrue("Non of the valid boards match with the current state", isValid);
+ }
+
+ /**
+ * Run only the test define for the current grid size if such test exist
+ *
+ * @param testCaseMap map containing all the tests per grid size (Point)
+ */
+ private boolean runTestCaseMap(Map<Point, ReorderTestCase> testCaseMap, String testName) {
+ Point iconGridDimensions = mLauncher.getWorkspace().getIconGridDimensions();
+ Log.d(TAG, "Running test " + testName + " for grid " + iconGridDimensions);
+ if (!testCaseMap.containsKey(iconGridDimensions)) {
+ Log.d(TAG, "The test " + testName + " doesn't support " + iconGridDimensions
+ + " grid layout");
+ return false;
+ }
+ runTestCase(testCaseMap.get(iconGridDimensions));
+
+ return true;
+ }
+
+ private void runTestCaseMapForAllGrids(Map<Point, ReorderTestCase> testCaseMap,
+ String testName) {
+ boolean runAtLeastOnce = false;
+ for (String grid : FOLDABLE_GRIDS) {
+ applyGridOption(grid);
+ mLauncher.waitForLauncherInitialized();
+ runAtLeastOnce |= runTestCaseMap(testCaseMap, testName);
+ }
+ Assume.assumeTrue("None of the grids are supported", runAtLeastOnce);
+ }
+
+ private void applyGridOption(Object argValue) {
+ String testProviderAuthority = mTargetContext.getPackageName() + ".grid_control";
+ Uri gridUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(testProviderAuthority)
+ .appendPath("default_grid")
+ .build();
+ ContentValues values = new ContentValues();
+ values.putObject("name", argValue);
+ Assert.assertEquals(1,
+ mTargetContext.getContentResolver().update(gridUri, values, null, null));
+ }
+
+ @Test
+ public void simpleReorder() throws Exception {
+ runTestCaseMap(getTestMap("ReorderWidgets/simple_reorder_case"),
+ "push_reorder_case");
+ }
+
+ @Test
+ public void pushTest() throws Exception {
+ runTestCaseMap(getTestMap("ReorderWidgets/push_reorder_case"),
+ "push_reorder_case");
+ }
+
+ @Test
+ public void fullReorder() throws Exception {
+ runTestCaseMap(getTestMap("ReorderWidgets/full_reorder_case"),
+ "full_reorder_case");
+ }
+
+ @Test
+ public void moveOutReorder() throws Exception {
+ runTestCaseMap(getTestMap("ReorderWidgets/move_out_reorder_case"),
+ "move_out_reorder_case");
+ }
+
+ @Test
+ public void multipleCellLayoutsSimpleReorder() throws Exception {
+ Assume.assumeTrue("Test doesn't support foldables", getFromLauncher(
+ l -> l.getWorkspace().getScreenWithId(0) instanceof MultipageCellLayout));
+ runTestCaseMapForAllGrids(getTestMap("ReorderWidgets/multiple_cell_layouts_simple_reorder"),
+ "multiple_cell_layouts_simple_reorder");
+ }
+
+ @Test
+ public void multipleCellLayoutsNoSpaceReorder() throws Exception {
+ Assume.assumeTrue("Test doesn't support foldables", getFromLauncher(
+ l -> l.getWorkspace().getScreenWithId(0) instanceof MultipageCellLayout));
+ runTestCaseMapForAllGrids(
+ getTestMap("ReorderWidgets/multiple_cell_layouts_no_space_reorder"),
+ "multiple_cell_layouts_no_space_reorder");
+ }
+
+ @Test
+ public void multipleCellLayoutsReorderToOtherSide() throws Exception {
+ Assume.assumeTrue("Test doesn't support foldables", getFromLauncher(
+ l -> l.getWorkspace().getScreenWithId(0) instanceof MultipageCellLayout));
+ runTestCaseMapForAllGrids(
+ getTestMap("ReorderWidgets/multiple_cell_layouts_reorder_other_side"),
+ "multiple_cell_layouts_reorder_other_side");
+ }
+
+ private void addTestCase(Iterator<CellLayoutTestCaseReader.TestSection> sections,
+ Map<Point, ReorderTestCase> testCaseMap) {
+ CellLayoutTestCaseReader.Board startBoard =
+ ((CellLayoutTestCaseReader.Board) sections.next());
+ CellLayoutTestCaseReader.Arguments point =
+ ((CellLayoutTestCaseReader.Arguments) sections.next());
+ CellLayoutTestCaseReader.Board endBoard =
+ ((CellLayoutTestCaseReader.Board) sections.next());
+ Point moveTo = new Point(Integer.parseInt(point.arguments[0]),
+ Integer.parseInt(point.arguments[1]));
+ testCaseMap.put(endBoard.gridSize,
+ new ReorderTestCase(startBoard.board, moveTo, endBoard.board));
+ }
+
+ private Map<Point, ReorderTestCase> getTestMap(String testPath) throws IOException {
+ Map<Point, ReorderTestCase> testCaseMap = new HashMap<>();
+ Iterator<CellLayoutTestCaseReader.TestSection> iterableSection =
+ CellLayoutTestCaseReader.readFromFile(testPath).parse().iterator();
+ while (iterableSection.hasNext()) {
+ addTestCase(iterableSection, testCaseMap);
+ }
+ return testCaseMap;
+ }
+}