/* * Copyright (C) 2024 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.folder import android.content.Context import android.graphics.Point import android.view.KeyEvent import android.view.View import android.view.inputmethod.EditorInfo import android.widget.TextView import androidx.core.view.isVisible import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.launcher3.Alarm import com.android.launcher3.DragSource import com.android.launcher3.DropTarget.DragObject import com.android.launcher3.LauncherAppState import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER import com.android.launcher3.OnAlarmListener import com.android.launcher3.R import com.android.launcher3.celllayout.board.FolderPoint import com.android.launcher3.celllayout.board.TestWorkspaceBuilder import com.android.launcher3.dragndrop.DragController import com.android.launcher3.dragndrop.DragOptions import com.android.launcher3.dragndrop.DragView import com.android.launcher3.folder.Folder.MIN_CONTENT_DIMEN import com.android.launcher3.folder.Folder.ON_EXIT_CLOSE_DELAY import com.android.launcher3.folder.Folder.SCROLL_LEFT import com.android.launcher3.folder.Folder.SCROLL_NONE import com.android.launcher3.folder.Folder.STATE_ANIMATING import com.android.launcher3.folder.Folder.STATE_CLOSED import com.android.launcher3.model.data.FolderInfo import com.android.launcher3.model.data.ItemInfo import com.android.launcher3.util.ActivityContextWrapper import com.android.launcher3.util.ModelTestExtensions.clearModelDb import java.util.ArrayList import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertFalse import junit.framework.TestCase.assertNull import junit.framework.TestCase.assertTrue import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito import org.mockito.Mockito.spy import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.kotlin.doNothing import org.mockito.kotlin.doReturn import org.mockito.kotlin.whenever /** Tests for [Folder] */ @SmallTest @RunWith(AndroidJUnit4::class) class FolderTest { private lateinit var context: Context private lateinit var workspaceBuilder: TestWorkspaceBuilder private lateinit var folder: Folder @Before fun setUp() { context = ActivityContextWrapper(ApplicationProvider.getApplicationContext()) workspaceBuilder = TestWorkspaceBuilder(context) folder = spy(Folder(context, null)) } @After fun tearDown() { LauncherAppState.getInstance(context).model.clearModelDb() } @Test fun `Undo a folder with 1 icon when onDropCompleted is called`() { val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) folder.mInfo = folderInfo folder.mInfo.getContents().removeAt(0) folder.mContent = Mockito.mock(FolderPagedView::class.java) val dragLayout = Mockito.mock(View::class.java) val dragObject = Mockito.mock(DragObject::class.java) folder.deleteFolderOnDropCompleted = false folder.onDropCompleted(dragLayout, dragObject, true) verify(folder, times(1)).replaceFolderWithFinalItem() assertEquals(folder.deleteFolderOnDropCompleted, false) } @Test fun `Do not undo a folder with 2 icons when onDropCompleted is called`() { val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) folder.mInfo = folderInfo folder.mContent = Mockito.mock(FolderPagedView::class.java) val dragLayout = Mockito.mock(View::class.java) val dragObject = Mockito.mock(DragObject::class.java) folder.deleteFolderOnDropCompleted = false folder.onDropCompleted(dragLayout, dragObject, true) verify(folder, times(0)).replaceFolderWithFinalItem() assertEquals(folder.deleteFolderOnDropCompleted, false) } @Test fun `Test that we accept valid item type ITEM_TYPE_APPLICATION`() { val itemInfo = Mockito.mock(ItemInfo::class.java) itemInfo.itemType = ITEM_TYPE_APPLICATION val willAcceptResult = Folder.willAccept(itemInfo) assertTrue(willAcceptResult) } @Test fun `Test that we accept valid item type ITEM_TYPE_DEEP_SHORTCUT`() { val itemInfo = Mockito.mock(ItemInfo::class.java) itemInfo.itemType = ITEM_TYPE_DEEP_SHORTCUT val willAcceptResult = Folder.willAccept(itemInfo) assertTrue(willAcceptResult) } @Test fun `Test that we accept valid item type ITEM_TYPE_APP_PAIR`() { val itemInfo = Mockito.mock(ItemInfo::class.java) itemInfo.itemType = ITEM_TYPE_APP_PAIR val willAcceptResult = Folder.willAccept(itemInfo) assertTrue(willAcceptResult) } @Test fun `Test that we do not accept invalid item type ITEM_TYPE_APPWIDGET`() { val itemInfo = Mockito.mock(ItemInfo::class.java) itemInfo.itemType = ITEM_TYPE_APPWIDGET val willAcceptResult = Folder.willAccept(itemInfo) assertFalse(willAcceptResult) } @Test fun `Test that we do not accept invalid item type ITEM_TYPE_FOLDER`() { val itemInfo = Mockito.mock(ItemInfo::class.java) itemInfo.itemType = ITEM_TYPE_FOLDER val willAcceptResult = Folder.willAccept(itemInfo) assertFalse(willAcceptResult) } @Test fun `We should not animate open if items is null or less than or equal to 1`() { folder.mInfo = Mockito.mock(FolderInfo::class.java) val shouldAnimateOpenResult = folder.shouldAnimateOpen(null) assertFalse(shouldAnimateOpenResult) assertFalse( folder.shouldAnimateOpen(arrayListOf(Mockito.mock(ItemInfo::class.java))) ) } @Test fun `We should animate open if items greater than 1`() { val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) folder.mInfo = folderInfo val shouldAnimateOpenResult = folder.shouldAnimateOpen(folder.mInfo.getContents()) assertTrue(shouldAnimateOpenResult) } @Test fun `Should be true if there is an open folder`() { val closeOpenFolderResult = folder.closeOpenFolder(Mockito.mock(Folder::class.java)) assertTrue(closeOpenFolderResult) } @Test fun `Should be false if the open folder is this folder`() { val closeOpenFolderResult = folder.closeOpenFolder(folder) assertFalse(closeOpenFolderResult) } @Test fun `Should be false if there is not an open folder`() { val closeOpenFolderResult = folder.closeOpenFolder(null) assertFalse(closeOpenFolderResult) } @Test fun `If drag is in progress we should set mItemAddedBackToSelfViaIcon to true`() { folder.itemAddedBackToSelfViaIcon = false folder.isDragInProgress = true folder.notifyDrop() assertTrue(folder.itemAddedBackToSelfViaIcon) } @Test fun `If drag is not in progress we should not set mItemAddedBackToSelfViaIcon to true`() { folder.itemAddedBackToSelfViaIcon = false folder.isDragInProgress = false folder.notifyDrop() assertFalse(folder.itemAddedBackToSelfViaIcon) } @Test fun `If launcher dragging is not enabled onLongClick should return true`() { `when`(folder.isLauncherDraggingEnabled).thenReturn(false) val onLongClickResult = folder.onLongClick(Mockito.mock(View::class.java)) assertTrue(onLongClickResult) } @Test fun `If launcher dragging is enabled we should return startDrag result`() { `when`(folder.isLauncherDraggingEnabled).thenReturn(true) val viewMock = Mockito.mock(View::class.java) val dragOptions = Mockito.mock(DragOptions::class.java) val onLongClickResult = folder.onLongClick(viewMock) assertEquals(onLongClickResult, folder.startDrag(viewMock, dragOptions)) verify(folder, times(1)).startDrag(viewMock, dragOptions) } @Test fun `Verify start drag works as intended when view is instanceof ItemInfo`() { val itemInfo = ItemInfo() itemInfo.rank = 5 val viewMock = Mockito.mock(View::class.java) val dragOptions = DragOptions() `when`(viewMock.tag).thenReturn(itemInfo) folder.dragController = Mockito.mock(DragController::class.java) folder.startDrag(viewMock, dragOptions) assertEquals(folder.mEmptyCellRank, 5) assertEquals(folder.currentDragView, viewMock) verify(folder, times(1)).addDragListener(dragOptions) verify(folder, times(1)).callBeginDragShared(viewMock, dragOptions) } @Test fun `Verify start drag works as intended when view is not instanceof ItemInfo`() { val viewMock = Mockito.mock(View::class.java) val dragOptions = DragOptions() folder.startDrag(viewMock, dragOptions) verify(folder, times(0)).addDragListener(dragOptions) verify(folder, times(0)).callBeginDragShared(viewMock, dragOptions) } @Test fun `Verify that onDragStart has an effect if dragSource is this folder`() { folder.itemsInvalidated = false folder.isDragInProgress = false folder.itemAddedBackToSelfViaIcon = true folder.currentDragView = Mockito.mock(View::class.java) val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) folder.mInfo = spy(folderInfo) val dragObject = DragObject(context) dragObject.dragInfo = Mockito.mock(ItemInfo::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) dragObject.dragSource = folder folder.onDragStart(dragObject, DragOptions()) verify(folder.mContent, times(1)).removeItem(folder.currentDragView) verify(folder, times(1)).removeFolderContent(true, dragObject.dragInfo) assertTrue(folder.itemsInvalidated) assertTrue(folder.isDragInProgress) assertFalse(folder.itemAddedBackToSelfViaIcon) } @Test fun `Verify that onDragStart has no effects if dragSource is not this folder`() { folder.itemsInvalidated = false folder.isDragInProgress = false folder.itemAddedBackToSelfViaIcon = true folder.mContent = Mockito.mock(FolderPagedView::class.java) val dragObject = DragObject(context) dragObject.dragSource = Mockito.mock(DragSource::class.java) folder.onDragStart(dragObject, DragOptions()) verify(folder.mContent, times(0)).removeItem(folder.currentDragView) assertFalse(folder.itemsInvalidated) assertFalse(folder.isDragInProgress) assertTrue(folder.itemAddedBackToSelfViaIcon) } @Test fun `Verify onDragEnd that we call completeDragExit and set drag in progress false`() { doNothing().`when`(folder).completeDragExit() folder.isExternalDrag = true folder.isDragInProgress = true folder.dragController = Mockito.mock(DragController::class.java) folder.onDragEnd() verify(folder, times(1)).completeDragExit() verify(folder.dragController, times(1)).removeDragListener(folder) assertFalse(folder.isDragInProgress) } @Test fun `Verify onDragEnd that we do not call completeDragExit and set drag in progress false`() { folder.isExternalDrag = false folder.isDragInProgress = true folder.dragController = Mockito.mock(DragController::class.java) folder.onDragEnd() verify(folder, times(0)).completeDragExit() verify(folder.dragController, times(1)).removeDragListener(folder) assertFalse(folder.isDragInProgress) } @Test fun `startEditingFolderName should set hint to empty and showLabelSuggestions`() { doNothing().`when`(folder).showLabelSuggestions() folder.isEditingName = false folder.folderName = FolderNameEditText(context) folder.folderName.hint = "hello" folder.startEditingFolderName() verify(folder, times(1)).showLabelSuggestions() assertEquals("", folder.folderName.hint) assertTrue(folder.isEditingName) } @Test fun `Ensure we set the title and hint correctly onBackKey when we have a new title`() { val expectedHint = null val expectedTitle = "hello" folder.isEditingName = true folder.folderName = spy(FolderNameEditText(context)) folder.folderName.setText(expectedTitle) val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) folder.mInfo = spy(folderInfo) folder.mInfo.title = "world" folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.onBackKey() assertEquals(expectedTitle, folder.mInfo.title) verify(folder.mFolderIcon, times(1)).onTitleChanged(expectedTitle) assertEquals(expectedHint, folder.folderName.hint) assertFalse(folder.isEditingName) verify(folder.folderName, times(1)).clearFocus() } @Test fun `Ensure we set the title and hint correctly onBackKey when we do not have a new title`() { val expectedHint = context.getString(R.string.folder_hint_text) val expectedTitle = "" folder.isEditingName = true folder.folderName = spy(FolderNameEditText(context)) folder.folderName.setText(expectedTitle) val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) folder.mInfo = spy(folderInfo) folder.mInfo.title = "world" folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.onBackKey() assertEquals(expectedTitle, folder.mInfo.title) verify(folder.mFolderIcon, times(1)).onTitleChanged(expectedTitle) assertEquals(expectedHint, folder.folderName.hint) assertFalse(folder.isEditingName) verify(folder.folderName, times(1)).clearFocus() } @Test fun `ensure onEditorAction calls dispatchBackKey when actionId is IME_ACTION_DONE`() { folder.folderName = Mockito.mock(FolderNameEditText::class.java) val result = folder.onEditorAction( Mockito.mock(TextView::class.java), EditorInfo.IME_ACTION_DONE, Mockito.mock(KeyEvent::class.java), ) assertTrue(result) verify(folder.folderName, times(1)).dispatchBackKey() } @Test fun `ensure onEditorAction does not call dispatchBackKey when actionId is not IME_ACTION_DONE`() { folder.folderName = Mockito.mock(FolderNameEditText::class.java) val result = folder.onEditorAction( Mockito.mock(TextView::class.java), EditorInfo.IME_ACTION_NONE, Mockito.mock(KeyEvent::class.java), ) assertFalse(result) verify(folder.folderName, times(0)).dispatchBackKey() } @Test fun `in completeDragExit we close the folder when mIsOpen`() { doNothing().`when`(folder).close(true) folder.setIsOpen(true) folder.rearrangeOnClose = false folder.completeDragExit() verify(folder, times(1)).close(true) assertTrue(folder.rearrangeOnClose) } @Test fun `in completeDragExit we want to rearrange on close when it is animating`() { folder.setIsOpen(false) folder.rearrangeOnClose = false folder.state = STATE_ANIMATING folder.completeDragExit() verify(folder, times(0)).close(true) assertTrue(folder.rearrangeOnClose) } @Test fun `in completeDragExit we want to call rearrangeChildren and clearDragInfo when not open and not animating`() { doNothing().`when`(folder).rearrangeChildren() doNothing().`when`(folder).clearDragInfo() folder.setIsOpen(false) folder.rearrangeOnClose = false folder.state = STATE_CLOSED folder.completeDragExit() verify(folder, times(0)).close(true) assertFalse(folder.rearrangeOnClose) verify(folder, times(1)).rearrangeChildren() verify(folder, times(1)).clearDragInfo() } @Test fun `clearDragInfo should set current drag view to null and isExternalDrag to false`() { folder.currentDragView = Mockito.mock(DragView::class.java) folder.isExternalDrag = true folder.clearDragInfo() assertNull(folder.currentDragView) assertFalse(folder.isExternalDrag) } @Test fun `onDragExit should set alarm if drag is not complete`() { folder.onExitAlarm = Mockito.mock(Alarm::class.java) val dragObject = Mockito.mock(DragObject::class.java) dragObject.dragComplete = false folder.onDragExit(dragObject) verify(folder.onExitAlarm, times(1)).setOnAlarmListener(folder.mOnExitAlarmListener) verify(folder.onExitAlarm, times(1)).setAlarm(ON_EXIT_CLOSE_DELAY.toLong()) } @Test fun `onDragExit should not set alarm if drag is complete`() { folder.onExitAlarm = Mockito.mock(Alarm::class.java) val dragObject = Mockito.mock(DragObject::class.java) dragObject.dragComplete = true folder.onDragExit(dragObject) verify(folder.onExitAlarm, times(0)).setOnAlarmListener(folder.mOnExitAlarmListener) verify(folder.onExitAlarm, times(0)).setAlarm(ON_EXIT_CLOSE_DELAY.toLong()) } @Test fun `onDragExit should not clear scroll hint if already SCROLL_NONE`() { folder.onExitAlarm = Mockito.mock(Alarm::class.java) val dragObject = Mockito.mock(DragObject::class.java) folder.scrollHintDir = SCROLL_NONE folder.mContent = Mockito.mock(FolderPagedView::class.java) folder.onDragExit(dragObject) verify(folder.mContent, times(0)).clearScrollHint() } @Test fun `onDragExit should clear scroll hint if not SCROLL_NONE and then set scroll hint to scroll none`() { folder.onExitAlarm = Mockito.mock(Alarm::class.java) val dragObject = Mockito.mock(DragObject::class.java) folder.scrollHintDir = SCROLL_LEFT folder.mContent = Mockito.mock(FolderPagedView::class.java) folder.onDragExit(dragObject) verify(folder.mContent, times(1)).clearScrollHint() assertEquals(folder.scrollHintDir, SCROLL_NONE) } @Test fun `onDragExit we should cancel reorder pause and hint alarms`() { folder.onExitAlarm = Mockito.mock(Alarm::class.java) val dragObject = Mockito.mock(DragObject::class.java) folder.scrollHintDir = SCROLL_NONE folder.mContent = Mockito.mock(FolderPagedView::class.java) folder.reorderAlarm = Mockito.mock(Alarm::class.java) folder.onScrollHintAlarm = Mockito.mock(Alarm::class.java) folder.scrollPauseAlarm = Mockito.mock(Alarm::class.java) folder.onDragExit(dragObject) verify(folder.reorderAlarm, times(1)).cancelAlarm() verify(folder.onScrollHintAlarm, times(1)).cancelAlarm() verify(folder.scrollPauseAlarm, times(1)).cancelAlarm() assertEquals(folder.scrollHintDir, SCROLL_NONE) } @Test fun `when calling prepareAccessibilityDrop we should cancel pending reorder alarm and call onAlarm`() { folder.reorderAlarm = Mockito.mock(Alarm::class.java) folder.mReorderAlarmListener = Mockito.mock(OnAlarmListener::class.java) `when`(folder.reorderAlarm.alarmPending()).thenReturn(true) folder.prepareAccessibilityDrop() verify(folder.reorderAlarm, times(1)).cancelAlarm() verify(folder.mReorderAlarmListener, times(1)).onAlarm(folder.reorderAlarm) } @Test fun `when calling prepareAccessibilityDrop we should not do anything if there is no pending alarm`() { folder.reorderAlarm = Mockito.mock(Alarm::class.java) folder.mReorderAlarmListener = Mockito.mock(OnAlarmListener::class.java) `when`(folder.reorderAlarm.alarmPending()).thenReturn(false) folder.prepareAccessibilityDrop() verify(folder.reorderAlarm, times(0)).cancelAlarm() verify(folder.mReorderAlarmListener, times(0)).onAlarm(folder.reorderAlarm) } @Test fun `isDropEnabled should be true as long as state is not STATE_ANIMATING`() { folder.state = STATE_CLOSED val isDropEnabled = folder.isDropEnabled assertTrue(isDropEnabled) } @Test fun `isDropEnabled should be false if state is STATE_ANIMATING`() { folder.state = STATE_ANIMATING val isDropEnabled = folder.isDropEnabled assertFalse(isDropEnabled) } @Test fun `getItemCount should return the number of items in the folder`() { val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) folder.mInfo = folderInfo val itemCount = folder.itemCount assertEquals(itemCount, 2) } @Test fun `hideItem should set the visibility of the corresponding ItemInfo to invisible`() { val itemInfo = ItemInfo() val view = View(context) view.isVisible = true doReturn(view).whenever(folder).getViewForInfo(itemInfo) folder.hideItem(itemInfo) assertFalse(view.isVisible) } @Test fun `showItem should set the visibility of the corresponding ItemInfo to visible`() { val itemInfo = ItemInfo() val view = View(context) view.isVisible = false doReturn(view).whenever(folder).getViewForInfo(itemInfo) folder.showItem(itemInfo) assertTrue(view.isVisible) } @Test fun `onDragEnter should cancel exit alarm and set the scroll area offset to dragRegionWidth divided by two minus xOffset`() { folder.mPrevTargetRank = 1 val dragObject = Mockito.mock(DragObject::class.java) val dragView = Mockito.mock(DragView::class.java) dragObject.dragView = dragView folder.onExitAlarm = Mockito.mock(Alarm::class.java) `when`(dragObject.dragView.getDragRegionWidth()).thenReturn(100) dragObject.xOffset = 20 folder.onDragEnter(dragObject) verify(folder.onExitAlarm, times(1)).cancelAlarm() assertEquals(-1, folder.mPrevTargetRank) assertEquals(30, folder.scrollAreaOffset) } @Test fun `acceptDrop should return true with the correct item type as a parameter`() { val dragObject = Mockito.mock(DragObject::class.java) val itemInfo = Mockito.mock(ItemInfo::class.java) itemInfo.itemType = ITEM_TYPE_APP_PAIR dragObject.dragInfo = itemInfo val result = folder.acceptDrop(dragObject) assertTrue(result) } @Test fun `acceptDrop should return false with the incorrect item type as a parameter`() { val dragObject = Mockito.mock(DragObject::class.java) val itemInfo = Mockito.mock(ItemInfo::class.java) itemInfo.itemType = ITEM_TYPE_APPWIDGET dragObject.dragInfo = itemInfo val result = folder.acceptDrop(dragObject) assertFalse(result) } @Test fun `rearrangeChildren should return early if content view are not bound`() { folder.mContent = Mockito.mock(FolderPagedView::class.java) folder.itemsInvalidated = false doReturn(false).whenever(folder.mContent).areViewsBound() folder.rearrangeChildren() verify(folder.mContent, times(0)).arrangeChildren(folder.iconsInReadingOrder) assertFalse(folder.itemsInvalidated) } @Test fun `rearrangeChildren should call arrange children and invalidate items`() { folder.mContent = Mockito.mock(FolderPagedView::class.java) folder.itemsInvalidated = false doReturn(true).whenever(folder.mContent).areViewsBound() val iconsInReadingOrderList = ArrayList() `when`(folder.iconsInReadingOrder).thenReturn(iconsInReadingOrderList) doNothing().`when`(folder.mContent).arrangeChildren(iconsInReadingOrderList) folder.rearrangeChildren() verify(folder.mContent, times(1)).arrangeChildren(folder.iconsInReadingOrder) assertTrue(folder.itemsInvalidated) } @Test fun `getItemCount should return the size of info getContents size`() { val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) folder.mInfo = folderInfo val itemCount = folder.itemCount assertEquals(2, itemCount) } @Test fun `replaceFolderWithFinalItem should set mDestroyed to true if we replace folder with final item`() { val launcherDelegate = Mockito.mock(LauncherDelegate::class.java) folder.mLauncherDelegate = launcherDelegate `when`(folder.mLauncherDelegate.replaceFolderWithFinalItem(folder)).thenReturn(true) folder.replaceFolderWithFinalItem() assertTrue(folder.isDestroyed) } @Test fun `replaceFolderWithFinalItem should set mDestroyed to false if we do not replace folder with final item`() { val launcherDelegate = Mockito.mock(LauncherDelegate::class.java) folder.mLauncherDelegate = launcherDelegate `when`(folder.mLauncherDelegate.replaceFolderWithFinalItem(folder)).thenReturn(false) folder.replaceFolderWithFinalItem() assertFalse(folder.isDestroyed) } @Test fun `getContentAreaHeight should return maxContentAreaHeight`() { folder.mContent = Mockito.mock(FolderPagedView::class.java) `when`(folder.mContent.desiredHeight).thenReturn(100) `when`(folder.maxContentAreaHeight).thenReturn(50) val height = folder.contentAreaHeight assertEquals(50, height) } @Test fun `getContentAreaHeight should return desiredHeight`() { folder.mContent = Mockito.mock(FolderPagedView::class.java) `when`(folder.mContent.desiredHeight).thenReturn(50) `when`(folder.maxContentAreaHeight).thenReturn(100) val height = folder.contentAreaHeight assertEquals(50, height) } @Test fun `getContentAreaHeight should return MIN_CONTENT_DIMEN`() { folder.mContent = Mockito.mock(FolderPagedView::class.java) `when`(folder.mContent.desiredHeight).thenReturn(1) `when`(folder.maxContentAreaHeight).thenReturn(2) val height = folder.contentAreaHeight assertEquals(MIN_CONTENT_DIMEN, height) } @Test fun `getContentAreaWidth should return desired width`() { folder.mContent = Mockito.mock(FolderPagedView::class.java) `when`(folder.mContent.desiredWidth).thenReturn(50) val width = folder.contentAreaWidth assertEquals(50, width) } @Test fun `getContentAreaWidth should return MIN_CONTENT_DIMEN`() { folder.mContent = Mockito.mock(FolderPagedView::class.java) `when`(folder.mContent.desiredWidth).thenReturn(1) val width = folder.contentAreaWidth assertEquals(MIN_CONTENT_DIMEN, width) } @Test fun `getFolderWidth should return padding left plus padding right plus desired width`() { folder.mContent = Mockito.mock(FolderPagedView::class.java) `when`(folder.mContent.desiredWidth).thenReturn(1) `when`(folder.paddingLeft).thenReturn(10) `when`(folder.paddingRight).thenReturn(10) val width = folder.folderWidth assertEquals(21, width) } @Test fun `getFolderHeight with no params should return getFolderHeight`() { folder.mContent = Mockito.mock(FolderPagedView::class.java) `when`(folder.contentAreaHeight).thenReturn(100) `when`(folder.getFolderHeight(folder.contentAreaHeight)).thenReturn(120) val height = folder.folderHeight assertEquals(120, height) } @Test fun `getFolderWidth with contentAreaHeight should return padding top plus padding bottom plus contentAreaHeight plus footer height`() { folder.mContent = Mockito.mock(FolderPagedView::class.java) `when`(folder.footerHeight).thenReturn(100) `when`(folder.paddingTop).thenReturn(10) `when`(folder.paddingBottom).thenReturn(10) val height = folder.getFolderHeight(100) assertEquals(220, height) } @Test fun `onRemove should call removeItem with the correct views`() { val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) val items = folderInfo.getContents().toTypedArray() folder.mInfo = folderInfo folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) val view1 = Mockito.mock(View::class.java) val view2 = Mockito.mock(View::class.java) doReturn(view1).whenever(folder).getViewForInfo(items[0]) doReturn(view2).whenever(folder).getViewForInfo(items[1]) doReturn(2).whenever(folder).itemCount folder.removeFolderContent(false, *items) verify(folder.mContent, times(1)).removeItem(view1) verify(folder.mContent, times(1)).removeItem(view2) } @Test fun `onRemove should set mRearrangeOnClose to true and not call rearrangeChildren if animating`() { val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) val items = folderInfo.getContents().toTypedArray() folder.mInfo = folderInfo folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) folder.state = STATE_ANIMATING val view1 = Mockito.mock(View::class.java) val view2 = Mockito.mock(View::class.java) doReturn(view1).whenever(folder).getViewForInfo(items[0]) doReturn(view2).whenever(folder).getViewForInfo(items[1]) doReturn(2).whenever(folder).itemCount folder.removeFolderContent(true, *items) assertTrue(folder.rearrangeOnClose) verify(folder, times(0)).rearrangeChildren() } @Test fun `onRemove should set not change mRearrangeOnClose and not call rearrangeChildren if not animating`() { val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) val items = folderInfo.getContents().toTypedArray() folder.mInfo = folderInfo folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) folder.state = STATE_CLOSED folder.rearrangeOnClose = false val view1 = Mockito.mock(View::class.java) val view2 = Mockito.mock(View::class.java) doReturn(view1).whenever(folder).getViewForInfo(items[0]) doReturn(view2).whenever(folder).getViewForInfo(items[1]) doReturn(2).whenever(folder).itemCount folder.removeFolderContent(false, *items) assertFalse(folder.rearrangeOnClose) verify(folder, times(1)).rearrangeChildren() } @Test fun `onRemove should call close if mIsOpen is true and item count is less than or equal to one`() { val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) val items = folderInfo.getContents().toTypedArray() folder.mInfo = folderInfo folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) val view1 = Mockito.mock(View::class.java) val view2 = Mockito.mock(View::class.java) doReturn(view1).whenever(folder).getViewForInfo(items[0]) doReturn(view2).whenever(folder).getViewForInfo(items[1]) doReturn(1).whenever(folder).itemCount folder.setIsOpen(true) doNothing().`when`(folder).close(true) folder.removeFolderContent(false, *items) verify(folder, times(1)).close(true) } @Test fun `onRemove should call replaceFolderWithFinalItem if mIsOpen is false and item count is less than or equal to one`() { val folderInfo = workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) val items = folderInfo.getContents().toTypedArray() folder.mInfo = folderInfo folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) val view1 = Mockito.mock(View::class.java) val view2 = Mockito.mock(View::class.java) doReturn(view1).whenever(folder).getViewForInfo(items[0]) doReturn(view2).whenever(folder).getViewForInfo(items[1]) doReturn(1).whenever(folder).itemCount folder.setIsOpen(false) folder.removeFolderContent(false, *items) verify(folder, times(1)).replaceFolderWithFinalItem() } companion object { const val TWO_ICON_FOLDER_TYPE = 'A' } }