diff --git a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java index 3ca05bce80..a32ce3c558 100644 --- a/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java +++ b/tests/src/com/android/launcher3/celllayout/CellLayoutBoard.java @@ -30,39 +30,117 @@ import java.util.Set; public class CellLayoutBoard { + public static class CellType { + // The cells marked by this will be filled by 1x1 widgets and will be ignored when + // validating + public static final char IGNORE = 'x'; + // The cells marked by this will be filled by app icons + public static final char ICON = 'i'; + // Empty space + public static final char EMPTY = '-'; + // Widget that will be saved as "main widget" for easier retrieval + public static final char MAIN_WIDGET = 'm'; + // Everything else will be consider a widget + } + + public static class WidgetRect { + public char mType; + public Rect mBounds; + + WidgetRect(char type, Rect bounds) { + this.mType = type; + this.mBounds = bounds; + } + + int getSpanX() { + return mBounds.right - mBounds.left + 1; + } + + int getSpanY() { + return mBounds.top - mBounds.bottom + 1; + } + + int getCellX() { + return mBounds.left; + } + + int getCellY() { + return mBounds.bottom; + } + + boolean shouldIgnore() { + return this.mType == CellType.IGNORE; + } + + @Override + public String toString() { + return "WidgetRect type = " + mType + " bounds = " + mBounds.toString(); + } + } + + public static class IconPoint { + public Point coord; + public char mType; + + public IconPoint(Point coord, char type) { + this.coord = coord; + mType = type; + } + + public char getType() { + return mType; + } + + public void setType(char type) { + mType = type; + } + + public Point getCoord() { + return coord; + } + + public void setCoord(Point coord) { + this.coord = coord; + } + } + static final int INFINITE = 99999; - char[][] mBoard = new char[30][30]; + char[][] mWidget = new char[30][30]; - List mWidgetsRects = new ArrayList<>(); - Map mWidgetsMap = new HashMap<>(); + List mWidgetsRects = new ArrayList<>(); + Map mWidgetsMap = new HashMap<>(); - List mIconPoints = new ArrayList<>(); - Map mIconsMap = new HashMap<>(); + List mIconPoints = new ArrayList<>(); + Map mIconsMap = new HashMap<>(); Point mMain = new Point(); CellLayoutBoard() { - for (int x = 0; x < mBoard.length; x++) { - for (int y = 0; y < mBoard[0].length; y++) { - mBoard[x][y] = '-'; + for (int x = 0; x < mWidget.length; x++) { + for (int y = 0; y < mWidget[0].length; y++) { + mWidget[x][y] = CellType.EMPTY; } } } - public List getWidgets() { + public List getWidgets() { return mWidgetsRects; } + public List getIcons() { + return mIconPoints; + } + public Point getMain() { return mMain; } - public TestBoardWidget getWidgetRect(char c) { + public WidgetRect getWidgetRect(char c) { return mWidgetsMap.get(c); } - public static TestBoardWidget getWidgetRect(int x, int y, Set used, char[][] board) { + public static WidgetRect getWidgetRect(int x, int y, Set used, char[][] board) { char type = board[x][y]; Queue search = new ArrayDeque(); Point current = new Point(x, y); @@ -91,20 +169,20 @@ public class CellLayoutBoard { } } } - return new TestBoardWidget(type, widgetRect); + return new WidgetRect(type, widgetRect); } public static boolean isWidget(char type) { - return type != 'i' && type != '-'; + return type != CellType.ICON && type != CellType.EMPTY; } public static boolean isIcon(char type) { - return type == 'i'; + return type == CellType.ICON; } - private static List getRects(char[][] board) { + private static List getRects(char[][] board) { Set used = new HashSet<>(); - List widgetsRects = new ArrayList<>(); + List widgetsRects = new ArrayList<>(); for (int x = 0; x < board.length; x++) { for (int y = 0; y < board[0].length; y++) { if (!used.contains(new Point(x, y)) && isWidget(board[x][y])) { @@ -115,12 +193,12 @@ public class CellLayoutBoard { return widgetsRects; } - private static List getIconPoints(char[][] board) { - List iconPoints = new ArrayList<>(); + private static List getIconPoints(char[][] board) { + List iconPoints = new ArrayList<>(); for (int x = 0; x < board.length; x++) { for (int y = 0; y < board[0].length; y++) { if (isIcon(board[x][y])) { - iconPoints.add(new TestBoardAppIcon(new Point(x, y), board[x][y])); + iconPoints.add(new IconPoint(new Point(x, y), board[x][y])); } } } @@ -135,18 +213,18 @@ public class CellLayoutBoard { String line = lines[y]; for (int x = 0; x < line.length(); x++) { char c = line.charAt(x); - if (c == 'm') { + if (c == CellType.MAIN_WIDGET) { board.mMain = new Point(x, y); } - if (c != '-') { - board.mBoard[x][y] = line.charAt(x); + if (c != CellType.EMPTY) { + board.mWidget[x][y] = line.charAt(x); } } } - board.mWidgetsRects = getRects(board.mBoard); + board.mWidgetsRects = getRects(board.mWidget); board.mWidgetsRects.forEach( widgetRect -> board.mWidgetsMap.put(widgetRect.mType, widgetRect)); - board.mIconPoints = getIconPoints(board.mBoard); + board.mIconPoints = getIconPoints(board.mWidget); return board; } } diff --git a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java index 5f5dfea2c3..93fbf97e99 100644 --- a/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java +++ b/tests/src/com/android/launcher3/celllayout/ReorderWidgets.java @@ -15,16 +15,13 @@ */ package com.android.launcher3.celllayout; -import static com.android.launcher3.util.WidgetUtils.createWidgetInfo; - +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import android.graphics.Point; -import android.graphics.Rect; import android.util.Log; import android.view.View; -import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -34,13 +31,14 @@ import com.android.launcher3.celllayout.testcases.MoveOutReorderCase; import com.android.launcher3.celllayout.testcases.PushReorderCase; import com.android.launcher3.celllayout.testcases.ReorderTestCase; import com.android.launcher3.celllayout.testcases.SimpleReorderCase; -import com.android.launcher3.model.data.LauncherAppWidgetInfo; +import com.android.launcher3.tapl.Widget; +import com.android.launcher3.tapl.WidgetResizeFrame; import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.ui.TaplTestsLauncher3; -import com.android.launcher3.ui.TestViewHelpers; import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord; import com.android.launcher3.util.rule.ShellCommandRule; -import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; +import com.android.launcher3.views.DoubleShadowBubbleTextView; +import com.android.launcher3.widget.LauncherAppWidgetHostView; import org.junit.Assume; import org.junit.Before; @@ -60,6 +58,8 @@ public class ReorderWidgets extends AbstractLauncherUiTest { private static final String TAG = ReorderWidgets.class.getSimpleName(); + TestWorkspaceBuilder mBoardBuilder; + private View getViewAt(int cellX, int cellY) { return getFromLauncher(l -> l.getWorkspace().getScreenWithId( l.getWorkspace().getScreenIdForPageIndex(0)).getChildAt(cellX, cellY)); @@ -76,6 +76,7 @@ public class ReorderWidgets extends AbstractLauncherUiTest { @Before public void setup() throws Throwable { + mBoardBuilder = new TestWorkspaceBuilder(this); TaplTestsLauncher3.initialize(this); clearHomescreen(); } @@ -86,78 +87,44 @@ public class ReorderWidgets extends AbstractLauncherUiTest { private boolean validateBoard(CellLayoutBoard board) { boolean match = true; Point cellDimensions = getCellDimensions(); - for (TestBoardWidget widgetRect: board.getWidgets()) { + for (CellLayoutBoard.WidgetRect widgetRect: board.getWidgets()) { if (widgetRect.shouldIgnore()) { continue; } View widget = getViewAt(widgetRect.getCellX(), widgetRect.getCellY()); + assertTrue("The view selected at " + board + " is not a widget", + widget instanceof LauncherAppWidgetHostView); match &= widgetRect.getSpanX() == Math.round(widget.getWidth() / (float) cellDimensions.x); match &= widgetRect.getSpanY() == Math.round(widget.getHeight() / (float) cellDimensions.y); if (!match) return match; } + for (CellLayoutBoard.IconPoint iconPoint : board.getIcons()) { + View icon = getViewAt(iconPoint.getCoord().x, iconPoint.getCoord().y); + assertTrue("The view selected at " + iconPoint.coord + " is not an Icon", + icon instanceof DoubleShadowBubbleTextView); + } return match; } - /** - * Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases. - */ - private void fillWithWidgets(TestBoardWidget widgetRect) { - int initX = widgetRect.getCellX(); - int initY = widgetRect.getCellY(); - for (int x = 0; x < widgetRect.getSpanX(); x++) { - for (int y = 0; y < widgetRect.getSpanY(); y++) { - int auxX = initX + x; - int auxY = initY + y; - try { - // this widgets are filling, we don't care if we can't place them - addWidgetInCell( - new TestBoardWidget('x', - new Rect(auxX, auxY, auxX, auxY)) - ); - } catch (Exception e) { - Log.d(TAG, "Unable to place filling widget at " + auxX + "," + auxY); - } - } - } - } - - private void addWidgetInCell(TestBoardWidget widgetRect) { - LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false); - LauncherAppWidgetInfo item = createWidgetInfo(info, - ApplicationProvider.getApplicationContext(), true); - item.cellX = widgetRect.getCellX(); - item.cellY = widgetRect.getCellY(); - - item.spanX = widgetRect.getSpanX(); - item.spanY = widgetRect.getSpanY(); - addItemToScreen(item); - } - - private void addCorrespondingWidgetRect(TestBoardWidget widgetRect) { - if (widgetRect.mType == 'x') { - fillWithWidgets(widgetRect); - } else { - addWidgetInCell(widgetRect); - } - } - private void runTestCase(ReorderTestCase testCase) { Point mainWidgetCellPos = testCase.mStart.getMain(); - testCase.mStart.getWidgets().forEach(this::addCorrespondingWidgetRect); + mBoardBuilder.buildBoard(testCase.mStart); - mLauncher.getWorkspace() - .getWidgetAtCell(mainWidgetCellPos.x, mainWidgetCellPos.y) - .dragWidgetToWorkspace(testCase.moveMainTo.x, testCase.moveMainTo.y) - .dismiss(); // dismiss resize frame + Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.x, + mainWidgetCellPos.y); + assertNotNull(widget); + WidgetResizeFrame resizeFrame = widget.dragWidgetToWorkspace(testCase.moveMainTo.x, + testCase.moveMainTo.y); + resizeFrame.dismiss(); boolean isValid = false; for (CellLayoutBoard board : testCase.mEnd) { isValid |= validateBoard(board); } - assertTrue("None of the valid boards match with the current state", isValid); + assertTrue("Non of the valid boards match with the current state", isValid); } /** diff --git a/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java new file mode 100644 index 0000000000..10e399dfd5 --- /dev/null +++ b/tests/src/com/android/launcher3/celllayout/TestWorkspaceBuilder.java @@ -0,0 +1,110 @@ +/* + * 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 com.android.launcher3.util.WidgetUtils.createWidgetInfo; + +import android.content.ComponentName; +import android.graphics.Rect; +import android.os.Process; +import android.os.UserHandle; +import android.util.Log; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.launcher3.LauncherSettings; +import com.android.launcher3.model.data.AppInfo; +import com.android.launcher3.model.data.LauncherAppWidgetInfo; +import com.android.launcher3.model.data.WorkspaceItemInfo; +import com.android.launcher3.ui.AbstractLauncherUiTest; +import com.android.launcher3.ui.TestViewHelpers; +import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; + +public class TestWorkspaceBuilder { + + private static final ComponentName APP_COMPONENT_NAME = new ComponentName( + "com.google.android.calculator", "com.android.calculator2.Calculator"); + + public AbstractLauncherUiTest mTest; + + private UserHandle mMyUser; + + public TestWorkspaceBuilder(AbstractLauncherUiTest test) { + mTest = test; + mMyUser = Process.myUserHandle(); + } + + private static final String TAG = "CellLayoutBoardBuilder"; + + /** + * Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases. + */ + private void fillWithWidgets(CellLayoutBoard.WidgetRect widgetRect) { + int initX = widgetRect.getCellX(); + int initY = widgetRect.getCellY(); + for (int x = initX; x < initX + widgetRect.getSpanX(); x++) { + for (int y = initY; y < initY + widgetRect.getSpanY(); y++) { + try { + // this widgets are filling, we don't care if we can't place them + addWidgetInCell( + new CellLayoutBoard.WidgetRect(CellLayoutBoard.CellType.IGNORE, + new Rect(x, y, x, y)) + ); + } catch (Exception e) { + Log.d(TAG, "Unable to place filling widget at " + x + "," + y); + } + } + } + } + + private void addWidgetInCell(CellLayoutBoard.WidgetRect widgetRect) { + LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(mTest, false); + LauncherAppWidgetInfo item = createWidgetInfo(info, + ApplicationProvider.getApplicationContext(), true); + + item.cellX = widgetRect.getCellX(); + item.cellY = widgetRect.getCellY(); + item.spanX = widgetRect.getSpanX(); + item.spanY = widgetRect.getSpanY(); + mTest.addItemToScreen(item); + } + + private void addIconInCell(CellLayoutBoard.IconPoint iconPoint) { + AppInfo appInfo = new AppInfo(APP_COMPONENT_NAME, "test icon", mMyUser, + AppInfo.makeLaunchIntent(APP_COMPONENT_NAME)); + + appInfo.cellX = iconPoint.getCoord().x; + appInfo.cellY = iconPoint.getCoord().y; + appInfo.minSpanY = appInfo.minSpanX = appInfo.spanX = appInfo.spanY = 1; + appInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP; + appInfo.componentName = APP_COMPONENT_NAME; + + mTest.addItemToScreen(new WorkspaceItemInfo(appInfo)); + } + + private void addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect) { + if (widgetRect.mType == 'x') { + fillWithWidgets(widgetRect); + } else { + addWidgetInCell(widgetRect); + } + } + + public void buildBoard(CellLayoutBoard board) { + board.getWidgets().forEach(this::addCorrespondingWidgetRect); + board.getIcons().forEach(this::addIconInCell); + } +} diff --git a/tests/src/com/android/launcher3/celllayout/testcases/FullReorderCase.java b/tests/src/com/android/launcher3/celllayout/testcases/FullReorderCase.java index 1326389ab7..94e55cfbde 100644 --- a/tests/src/com/android/launcher3/celllayout/testcases/FullReorderCase.java +++ b/tests/src/com/android/launcher3/celllayout/testcases/FullReorderCase.java @@ -19,6 +19,10 @@ import android.graphics.Point; import java.util.Map; +/** + * The grids represent the workspace to be build by TestWorkspaceBuilder, to see what each character + * in the board mean refer to {@code CellType} + */ public class FullReorderCase { /** 5x5 Test diff --git a/tests/src/com/android/launcher3/celllayout/testcases/MoveOutReorderCase.java b/tests/src/com/android/launcher3/celllayout/testcases/MoveOutReorderCase.java index 1701390268..a222d3d551 100644 --- a/tests/src/com/android/launcher3/celllayout/testcases/MoveOutReorderCase.java +++ b/tests/src/com/android/launcher3/celllayout/testcases/MoveOutReorderCase.java @@ -19,6 +19,10 @@ import android.graphics.Point; import java.util.Map; +/** + * The grids represent the workspace to be build by TestWorkspaceBuilder, to see what each character + * in the board mean refer to {@code CellType} + */ public class MoveOutReorderCase { /** 5x5 Test diff --git a/tests/src/com/android/launcher3/celllayout/testcases/PushReorderCase.java b/tests/src/com/android/launcher3/celllayout/testcases/PushReorderCase.java index bb8d5e9631..e16ff42a8b 100644 --- a/tests/src/com/android/launcher3/celllayout/testcases/PushReorderCase.java +++ b/tests/src/com/android/launcher3/celllayout/testcases/PushReorderCase.java @@ -19,6 +19,10 @@ import android.graphics.Point; import java.util.Map; +/** + * The grids represent the workspace to be build by TestWorkspaceBuilder, to see what each character + * in the board mean refer to {@code CellType} + */ public class PushReorderCase { /** 5x5 Test diff --git a/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java b/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java index 30269a0f5d..546c48bccb 100644 --- a/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java +++ b/tests/src/com/android/launcher3/celllayout/testcases/SimpleReorderCase.java @@ -19,6 +19,10 @@ import android.graphics.Point; import java.util.Map; +/** + * The grids represent the workspace to be build by TestWorkspaceBuilder, to see what each character + * in the board mean refer to {@code CellType} + */ public class SimpleReorderCase { /** 5x5 Test diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 304153f53f..a66b09a87d 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -319,7 +319,7 @@ public abstract class AbstractLauncherUiTest { /** * Adds {@param item} on the homescreen on the 0th screen */ - protected void addItemToScreen(ItemInfo item) { + public void addItemToScreen(ItemInfo item) { WidgetUtils.addItemToScreen(item, mTargetContext); resetLoaderState();