1 /* 2 * Copyright (C) 2016 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.documentsui.picker; 18 19 import static com.android.documentsui.base.State.ACTION_CREATE; 20 import static com.android.documentsui.base.State.ACTION_GET_CONTENT; 21 import static com.android.documentsui.base.State.ACTION_OPEN; 22 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertTrue; 25 26 import android.database.MatrixCursor; 27 import android.provider.DocumentsContract.Document; 28 import android.provider.DocumentsContract.Root; 29 30 import androidx.test.filters.SmallTest; 31 import androidx.test.runner.AndroidJUnit4; 32 33 import com.android.documentsui.DirectoryResult; 34 import com.android.documentsui.Model; 35 import com.android.documentsui.R; 36 import com.android.documentsui.base.DocumentInfo; 37 import com.android.documentsui.base.RootInfo; 38 import com.android.documentsui.base.State; 39 import com.android.documentsui.roots.RootCursorWrapper; 40 import com.android.documentsui.testing.TestDirectoryDetails; 41 import com.android.documentsui.testing.TestFeatures; 42 import com.android.documentsui.testing.TestMenu; 43 import com.android.documentsui.testing.TestMenuItem; 44 import com.android.documentsui.testing.TestSearchViewManager; 45 import com.android.documentsui.testing.TestSelectionDetails; 46 47 import org.junit.Before; 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 51 @RunWith(AndroidJUnit4.class) 52 @SmallTest 53 public final class MenuManagerTest { 54 55 private TestMenu testMenu; 56 57 /* Directory Context Menu items */ 58 private TestMenuItem dirShare; 59 private TestMenuItem dirOpen; 60 private TestMenuItem dirOpenWith; 61 private TestMenuItem dirCutToClipboard; 62 private TestMenuItem dirCopyToClipboard; 63 private TestMenuItem dirPasteFromClipboard; 64 private TestMenuItem dirCreateDir; 65 private TestMenuItem dirSelectAll; 66 private TestMenuItem dirRename; 67 private TestMenuItem dirDelete; 68 private TestMenuItem dirViewInOwner; 69 private TestMenuItem dirOpenInNewWindow; 70 private TestMenuItem dirPasteIntoFolder; 71 72 /* Root List Context Menu items */ 73 private TestMenuItem rootEjectRoot; 74 private TestMenuItem rootOpenInNewWindow; 75 private TestMenuItem rootPasteIntoFolder; 76 private TestMenuItem rootSettings; 77 78 /* Action Mode menu items */ 79 private TestMenuItem actionModeOpen; 80 private TestMenuItem actionModeOpenWith; 81 private TestMenuItem actionModeSelect; 82 private TestMenuItem actionModeShare; 83 private TestMenuItem actionModeDelete; 84 private TestMenuItem actionModeSelectAll; 85 private TestMenuItem actionModeCopyTo; 86 private TestMenuItem actionModeExtractTo; 87 private TestMenuItem actionModeMoveTo; 88 private TestMenuItem actionModeCompress; 89 private TestMenuItem actionModeRename; 90 private TestMenuItem actionModeViewInOwner; 91 private TestMenuItem actionModeSort; 92 93 /* Option Menu items */ 94 private TestMenuItem optionSearch; 95 private TestMenuItem optionDebug; 96 private TestMenuItem optionNewWindow; 97 private TestMenuItem optionCreateDir; 98 private TestMenuItem optionSelectAll; 99 private TestMenuItem optionAdvanced; 100 private TestMenuItem optionSettings; 101 private TestMenuItem optionSort; 102 103 private TestMenuItem subOptionGrid; 104 private TestMenuItem subOptionList; 105 106 private TestSelectionDetails selectionDetails; 107 private TestDirectoryDetails dirDetails; 108 private TestSearchViewManager testSearchManager; 109 private State state = new State(); 110 private RootInfo testRootInfo; 111 private DocumentInfo testDocInfo; 112 private MenuManager mgr; 113 114 @Before setUp()115 public void setUp() { 116 testMenu = TestMenu.create(); 117 dirShare = testMenu.findItem(R.id.dir_menu_share); 118 dirOpen = testMenu.findItem(R.id.dir_menu_open); 119 dirOpenWith = testMenu.findItem(R.id.dir_menu_open_with); 120 dirCutToClipboard = testMenu.findItem(R.id.dir_menu_cut_to_clipboard); 121 dirCopyToClipboard = testMenu.findItem(R.id.dir_menu_copy_to_clipboard); 122 dirPasteFromClipboard = testMenu.findItem(R.id.dir_menu_paste_from_clipboard); 123 dirCreateDir = testMenu.findItem(R.id.dir_menu_create_dir); 124 dirSelectAll = testMenu.findItem(R.id.dir_menu_select_all); 125 dirRename = testMenu.findItem(R.id.dir_menu_rename); 126 dirDelete = testMenu.findItem(R.id.dir_menu_delete); 127 dirViewInOwner = testMenu.findItem(R.id.dir_menu_view_in_owner); 128 dirOpenInNewWindow = testMenu.findItem(R.id.dir_menu_open_in_new_window); 129 dirPasteIntoFolder = testMenu.findItem(R.id.dir_menu_paste_into_folder); 130 131 rootEjectRoot = testMenu.findItem(R.id.root_menu_eject_root); 132 rootOpenInNewWindow = testMenu.findItem(R.id.root_menu_open_in_new_window); 133 rootPasteIntoFolder = testMenu.findItem(R.id.root_menu_paste_into_folder); 134 rootSettings = testMenu.findItem(R.id.root_menu_settings); 135 136 actionModeOpenWith = testMenu.findItem(R.id.action_menu_open_with); 137 actionModeSelect = testMenu.findItem(R.id.action_menu_select); 138 actionModeShare = testMenu.findItem(R.id.action_menu_share); 139 actionModeDelete = testMenu.findItem(R.id.action_menu_delete); 140 actionModeSelectAll = testMenu.findItem(R.id.action_menu_select_all); 141 actionModeCopyTo = testMenu.findItem(R.id.action_menu_copy_to); 142 actionModeExtractTo = testMenu.findItem(R.id.action_menu_extract_to); 143 actionModeMoveTo = testMenu.findItem(R.id.action_menu_move_to); 144 actionModeCompress = testMenu.findItem(R.id.action_menu_compress); 145 actionModeRename = testMenu.findItem(R.id.action_menu_rename); 146 actionModeViewInOwner = testMenu.findItem(R.id.action_menu_view_in_owner); 147 actionModeSort = testMenu.findItem(R.id.action_menu_sort); 148 149 optionSearch = testMenu.findItem(R.id.option_menu_search); 150 optionDebug = testMenu.findItem(R.id.option_menu_debug); 151 optionNewWindow = testMenu.findItem(R.id.option_menu_new_window); 152 optionCreateDir = testMenu.findItem(R.id.option_menu_create_dir); 153 optionSelectAll = testMenu.findItem(R.id.option_menu_select_all); 154 optionAdvanced = testMenu.findItem(R.id.option_menu_advanced); 155 optionSettings = testMenu.findItem(R.id.option_menu_settings); 156 optionSort = testMenu.findItem(R.id.option_menu_sort); 157 158 // Menu actions on root title row. 159 subOptionGrid = testMenu.findItem(R.id.sub_menu_grid); 160 subOptionList = testMenu.findItem(R.id.sub_menu_list); 161 162 selectionDetails = new TestSelectionDetails(); 163 dirDetails = new TestDirectoryDetails(); 164 testSearchManager = new TestSearchViewManager(); 165 mgr = new MenuManager(testSearchManager, state, dirDetails); 166 167 testRootInfo = new RootInfo(); 168 testDocInfo = new DocumentInfo(); 169 state.action = ACTION_CREATE; 170 state.allowMultiple = true; 171 } 172 173 @Test testActionMenu()174 public void testActionMenu() { 175 mgr.updateActionMenu(testMenu, selectionDetails); 176 actionModeSelect.assertInvisible(); 177 actionModeDelete.assertInvisible(); 178 actionModeShare.assertInvisible(); 179 actionModeRename.assertInvisible(); 180 actionModeSelectAll.assertVisible(); 181 actionModeViewInOwner.assertInvisible(); 182 actionModeSort.assertVisible(); 183 actionModeSort.assertEnabled(); 184 } 185 186 @Test testActionMenu_selectAction()187 public void testActionMenu_selectAction() { 188 state.action = ACTION_OPEN; 189 mgr.updateActionMenu(testMenu, selectionDetails); 190 191 actionModeSelect.assertVisible(); 192 } 193 194 @Test testActionMenu_selectActionTitle()195 public void testActionMenu_selectActionTitle() { 196 state.action = ACTION_OPEN; 197 mgr.updateActionMenu(testMenu, selectionDetails); 198 199 actionModeSelect.assertTitle(R.string.menu_select); 200 } 201 202 @Test testActionMenu_getContentAction()203 public void testActionMenu_getContentAction() { 204 state.action = ACTION_GET_CONTENT; 205 mgr.updateActionMenu(testMenu, selectionDetails); 206 207 actionModeSelect.assertVisible(); 208 } 209 210 @Test testActionMenu_getContentActionTitle()211 public void testActionMenu_getContentActionTitle() { 212 state.action = ACTION_GET_CONTENT; 213 mgr.updateActionMenu(testMenu, selectionDetails); 214 215 actionModeSelect.assertTitle(R.string.menu_select); 216 } 217 218 @Test testActionMenu_notAllowMultiple()219 public void testActionMenu_notAllowMultiple() { 220 state.allowMultiple = false; 221 mgr.updateActionMenu(testMenu, selectionDetails); 222 223 actionModeSelectAll.assertInvisible(); 224 } 225 226 @Test testActionMenu_AllowMultiple()227 public void testActionMenu_AllowMultiple() { 228 state.allowMultiple = true; 229 mgr.updateActionMenu(testMenu, selectionDetails); 230 231 actionModeSelectAll.assertVisible(); 232 } 233 234 @Test testOptionMenu()235 public void testOptionMenu() { 236 mgr.updateOptionMenu(testMenu); 237 238 optionAdvanced.assertInvisible(); 239 optionAdvanced.assertTitle(R.string.menu_advanced_show); 240 optionCreateDir.assertDisabled(); 241 optionSort.assertEnabled(); 242 optionSort.assertVisible(); 243 assertTrue(testSearchManager.showMenuCalled()); 244 } 245 246 @Test testOptionMenu_notPicking()247 public void testOptionMenu_notPicking() { 248 state.action = ACTION_OPEN; 249 state.derivedMode = State.MODE_LIST; 250 mgr.updateOptionMenu(testMenu); 251 mgr.updateSubMenu(testMenu); 252 253 optionCreateDir.assertInvisible(); 254 subOptionGrid.assertVisible(); 255 subOptionList.assertInvisible(); 256 assertFalse(testSearchManager.showMenuCalled()); 257 } 258 259 @Test testOptionMenu_canCreateDirectory()260 public void testOptionMenu_canCreateDirectory() { 261 dirDetails.canCreateDirectory = true; 262 mgr.updateOptionMenu(testMenu); 263 264 optionCreateDir.assertEnabled(); 265 } 266 267 @Test testOptionMenu_showAdvanced()268 public void testOptionMenu_showAdvanced() { 269 state.showAdvanced = true; 270 state.showDeviceStorageOption = true; 271 mgr.updateOptionMenu(testMenu); 272 273 optionAdvanced.assertVisible(); 274 optionAdvanced.assertTitle(R.string.menu_advanced_hide); 275 } 276 277 @Test testOptionMenu_inRecents()278 public void testOptionMenu_inRecents() { 279 dirDetails.isInRecents = true; 280 mgr.updateOptionMenu(testMenu); 281 mgr.updateSubMenu(testMenu); 282 283 subOptionGrid.assertInvisible(); 284 subOptionList.assertInvisible(); 285 } 286 287 288 @Test testOptionMenu_onlyContainer()289 public void testOptionMenu_onlyContainer() { 290 state.allowMultiple = true; 291 mgr.updateModel(getTestModel(true)); 292 mgr.updateOptionMenu(testMenu); 293 294 optionSelectAll.assertVisible(); 295 optionSelectAll.assertDisabled(); 296 } 297 298 @Test testOptionMenu_containerAndFile()299 public void testOptionMenu_containerAndFile() { 300 state.allowMultiple = true; 301 mgr.updateModel(getTestModel(false)); 302 mgr.updateOptionMenu(testMenu); 303 304 optionSelectAll.assertVisible(); 305 optionSelectAll.assertEnabled(); 306 } 307 308 @Test testContextMenu_EmptyArea()309 public void testContextMenu_EmptyArea() { 310 dirDetails.hasItemsToPaste = false; 311 dirDetails.canCreateDoc = false; 312 dirDetails.canCreateDirectory = false; 313 314 mgr.updateContextMenuForContainer(testMenu); 315 316 dirSelectAll.assertVisible(); 317 dirSelectAll.assertEnabled(); 318 dirPasteFromClipboard.assertVisible(); 319 dirPasteFromClipboard.assertDisabled(); 320 dirCreateDir.assertVisible(); 321 dirCreateDir.assertDisabled(); 322 } 323 324 @Test testContextMenu_EmptyArea_NoItemToPaste()325 public void testContextMenu_EmptyArea_NoItemToPaste() { 326 dirDetails.hasItemsToPaste = false; 327 dirDetails.canCreateDoc = true; 328 329 mgr.updateContextMenuForContainer(testMenu); 330 331 dirSelectAll.assertVisible(); 332 dirSelectAll.assertEnabled(); 333 dirPasteFromClipboard.assertVisible(); 334 dirPasteFromClipboard.assertDisabled(); 335 dirCreateDir.assertVisible(); 336 dirCreateDir.assertDisabled(); 337 } 338 339 @Test testContextMenu_EmptyArea_CantCreateDoc()340 public void testContextMenu_EmptyArea_CantCreateDoc() { 341 dirDetails.hasItemsToPaste = true; 342 dirDetails.canCreateDoc = false; 343 344 mgr.updateContextMenuForContainer(testMenu); 345 346 dirSelectAll.assertVisible(); 347 dirSelectAll.assertEnabled(); 348 dirPasteFromClipboard.assertVisible(); 349 dirPasteFromClipboard.assertDisabled(); 350 dirCreateDir.assertVisible(); 351 dirCreateDir.assertDisabled(); 352 } 353 354 @Test testContextMenu_EmptyArea_canPaste()355 public void testContextMenu_EmptyArea_canPaste() { 356 dirDetails.hasItemsToPaste = true; 357 dirDetails.canCreateDoc = true; 358 359 mgr.updateContextMenuForContainer(testMenu); 360 361 dirSelectAll.assertVisible(); 362 dirSelectAll.assertEnabled(); 363 dirPasteFromClipboard.assertVisible(); 364 dirPasteFromClipboard.assertEnabled(); 365 dirCreateDir.assertVisible(); 366 dirCreateDir.assertDisabled(); 367 } 368 369 @Test testContextMenu_EmptyArea_CanCreateDirectory()370 public void testContextMenu_EmptyArea_CanCreateDirectory() { 371 dirDetails.canCreateDirectory = true; 372 373 mgr.updateContextMenuForContainer(testMenu); 374 375 dirSelectAll.assertVisible(); 376 dirSelectAll.assertEnabled(); 377 dirPasteFromClipboard.assertVisible(); 378 dirPasteFromClipboard.assertDisabled(); 379 dirCreateDir.assertVisible(); 380 dirCreateDir.assertEnabled(); 381 } 382 383 @Test testContextMenu_OnFile()384 public void testContextMenu_OnFile() { 385 mgr.updateContextMenuForFiles(testMenu, selectionDetails); 386 // We don't want share in pickers. 387 dirShare.assertInvisible(); 388 // We don't want openWith in pickers. 389 dirOpenWith.assertInvisible(); 390 dirCutToClipboard.assertVisible(); 391 dirCopyToClipboard.assertVisible(); 392 dirRename.assertInvisible(); 393 dirDelete.assertVisible(); 394 } 395 396 @Test testContextMenu_OnDirectory()397 public void testContextMenu_OnDirectory() { 398 selectionDetails.canPasteInto = true; 399 mgr.updateContextMenuForDirs(testMenu, selectionDetails); 400 // We don't want openInNewWindow in pickers 401 dirOpenInNewWindow.assertInvisible(); 402 dirCutToClipboard.assertVisible(); 403 dirCopyToClipboard.assertVisible(); 404 // Doesn't matter if directory is selected, we don't want pasteInto for PickerActivity 405 dirPasteIntoFolder.assertInvisible(); 406 dirRename.assertInvisible(); 407 dirDelete.assertVisible(); 408 } 409 410 @Test testContextMenu_OnMixedDocs()411 public void testContextMenu_OnMixedDocs() { 412 selectionDetails.containDirectories = true; 413 selectionDetails.containFiles = true; 414 selectionDetails.size = 2; 415 selectionDetails.canDelete = true; 416 mgr.updateContextMenu(testMenu, selectionDetails); 417 dirCutToClipboard.assertVisible(); 418 dirCopyToClipboard.assertVisible(); 419 dirDelete.assertVisible(); 420 } 421 422 @Test testContextMenu_OnMixedDocs_hasPartialFile()423 public void testContextMenu_OnMixedDocs_hasPartialFile() { 424 selectionDetails.containDirectories = true; 425 selectionDetails.containFiles = true; 426 selectionDetails.size = 2; 427 selectionDetails.containPartial = true; 428 selectionDetails.canDelete = true; 429 mgr.updateContextMenu(testMenu, selectionDetails); 430 dirCutToClipboard.assertVisible(); 431 dirCutToClipboard.assertDisabled(); 432 dirCopyToClipboard.assertVisible(); 433 dirCopyToClipboard.assertDisabled(); 434 dirDelete.assertVisible(); 435 dirDelete.assertEnabled(); 436 } 437 438 @Test testContextMenu_OnMixedDocs_hasUndeletableFile()439 public void testContextMenu_OnMixedDocs_hasUndeletableFile() { 440 selectionDetails.containDirectories = true; 441 selectionDetails.containFiles = true; 442 selectionDetails.size = 2; 443 selectionDetails.canDelete = false; 444 mgr.updateContextMenu(testMenu, selectionDetails); 445 dirCutToClipboard.assertVisible(); 446 dirCutToClipboard.assertDisabled(); 447 dirCopyToClipboard.assertVisible(); 448 dirCopyToClipboard.assertEnabled(); 449 dirDelete.assertVisible(); 450 dirDelete.assertDisabled(); 451 } 452 453 @Test testRootContextMenu()454 public void testRootContextMenu() { 455 mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo); 456 457 rootEjectRoot.assertInvisible(); 458 rootOpenInNewWindow.assertInvisible(); 459 rootPasteIntoFolder.assertInvisible(); 460 rootSettings.assertInvisible(); 461 } 462 463 @Test testRootContextMenu_hasRootSettings()464 public void testRootContextMenu_hasRootSettings() { 465 testRootInfo.flags = Root.FLAG_HAS_SETTINGS; 466 mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo); 467 468 rootSettings.assertInvisible(); 469 } 470 471 @Test testRootContextMenu_nonWritableRoot()472 public void testRootContextMenu_nonWritableRoot() { 473 dirDetails.hasItemsToPaste = true; 474 mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo); 475 476 rootPasteIntoFolder.assertInvisible(); 477 } 478 479 @Test testRootContextMenu_nothingToPaste()480 public void testRootContextMenu_nothingToPaste() { 481 testRootInfo.flags = Root.FLAG_SUPPORTS_CREATE; 482 dirDetails.hasItemsToPaste = false; 483 mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo); 484 485 rootPasteIntoFolder.assertInvisible(); 486 } 487 488 @Test testRootContextMenu_canEject()489 public void testRootContextMenu_canEject() { 490 testRootInfo.flags = Root.FLAG_SUPPORTS_EJECT; 491 mgr.updateRootContextMenu(testMenu, testRootInfo, testDocInfo); 492 493 rootEjectRoot.assertInvisible(); 494 } 495 getTestModel(boolean onlyDirectory)496 private Model getTestModel(boolean onlyDirectory) { 497 String[] COLUMNS = new String[]{ 498 RootCursorWrapper.COLUMN_AUTHORITY, 499 Document.COLUMN_DOCUMENT_ID, 500 Document.COLUMN_FLAGS, 501 Document.COLUMN_DISPLAY_NAME, 502 Document.COLUMN_SIZE, 503 Document.COLUMN_LAST_MODIFIED, 504 Document.COLUMN_MIME_TYPE 505 }; 506 MatrixCursor c = new MatrixCursor(COLUMNS); 507 for (int i = 0; i < 3; ++i) { 508 MatrixCursor.RowBuilder row = c.newRow(); 509 row.add(Document.COLUMN_DOCUMENT_ID, Integer.toString(i)); 510 row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR); 511 } 512 513 if (!onlyDirectory) { 514 MatrixCursor.RowBuilder row = c.newRow(); 515 row.add(Document.COLUMN_DOCUMENT_ID, "4"); 516 row.add(Document.COLUMN_MIME_TYPE, "image/jpg"); 517 } 518 519 DirectoryResult r = new DirectoryResult(); 520 r.cursor = c; 521 Model model = new Model(new TestFeatures()); 522 model.update(r); 523 524 return model; 525 } 526 } 527