Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package org.chromium.chrome.browser.photo_picker; | |
| 6 | |
| 7 import android.support.test.filters.LargeTest; | |
| 8 import android.support.v7.widget.RecyclerView; | |
| 9 import android.view.View; | |
| 10 import android.widget.Button; | |
| 11 | |
| 12 import org.chromium.base.ThreadUtils; | |
| 13 import org.chromium.base.test.util.RetryOnFailure; | |
| 14 import org.chromium.chrome.R; | |
| 15 import org.chromium.chrome.browser.ChromeActivity; | |
| 16 import org.chromium.chrome.browser.widget.selection.SelectionDelegate; | |
| 17 import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionO bserver; | |
| 18 import org.chromium.chrome.test.ChromeActivityTestCaseBase; | |
| 19 import org.chromium.chrome.test.util.browser.RecyclerViewTestUtils; | |
| 20 import org.chromium.content.browser.test.util.Criteria; | |
| 21 import org.chromium.content.browser.test.util.CriteriaHelper; | |
| 22 import org.chromium.content.browser.test.util.TouchCommon; | |
| 23 import org.chromium.ui.PhotoPickerListener; | |
| 24 | |
| 25 import java.util.ArrayList; | |
| 26 import java.util.Arrays; | |
| 27 import java.util.List; | |
| 28 import java.util.concurrent.Callable; | |
| 29 | |
| 30 /** | |
| 31 * Tests for the PhotoPickerDialog class. | |
| 32 */ | |
| 33 @RetryOnFailure | |
| 34 public class PhotoPickerDialogTest extends ChromeActivityTestCaseBase<ChromeActi vity> | |
| 35 implements PhotoPickerListener, SelectionObserver<PickerBitmap> { | |
| 36 // The dialog we are testing. | |
| 37 private PhotoPickerDialog mDialog; | |
| 38 | |
| 39 // The data to show in the dialog (A map of filepath to last-modified time). | |
| 40 // Map<String, Long> mTestFiles; | |
| 41 private List<PickerBitmap> mTestFiles; | |
| 42 | |
| 43 // The last action recorded in the dialog (e.g. photo selected). | |
| 44 private Action mLastActionRecorded; | |
| 45 | |
| 46 // The final set of photos picked by the dialog. Can be an empty array, if | |
| 47 // nothing was selected. | |
| 48 private String[] mLastSelectedPhotos; | |
| 49 | |
| 50 // The list of currently selected photos (built piecemeal). | |
| 51 private List<PickerBitmap> mCurrentPhotoSelection; | |
| 52 | |
| 53 public PhotoPickerDialogTest() { | |
| 54 super(ChromeActivity.class); | |
| 55 } | |
| 56 | |
| 57 // ChromeActivityTestCaseBase: | |
| 58 | |
| 59 @Override | |
| 60 protected void setUp() throws Exception { | |
| 61 super.setUp(); | |
| 62 | |
| 63 mTestFiles = new ArrayList<>(); | |
| 64 mTestFiles.add(new PickerBitmap("a", 5L, PickerBitmap.PICTURE)); | |
| 65 mTestFiles.add(new PickerBitmap("b", 4L, PickerBitmap.PICTURE)); | |
| 66 mTestFiles.add(new PickerBitmap("c", 3L, PickerBitmap.PICTURE)); | |
| 67 mTestFiles.add(new PickerBitmap("d", 2L, PickerBitmap.PICTURE)); | |
| 68 mTestFiles.add(new PickerBitmap("e", 1L, PickerBitmap.PICTURE)); | |
| 69 mTestFiles.add(new PickerBitmap("f", 0L, PickerBitmap.PICTURE)); | |
| 70 | |
| 71 /* | |
| 72 mTestFiles.add(new PickerBitmap("/storage/emulated/0/DCIM/Camera/IMG_201 70201_154701.jpg", | |
| 73 5L, PickerBitmap.PICTURE)); mTestFiles.add(new | |
|
Theresa
2017/05/19 16:52:42
nit: remove this comment block
Finnur
2017/05/23 13:19:50
Oops. :) Done.
| |
| 74 PickerBitmap("/storage/emulated/0/DCIM/Camera/IMG_20170201_154704.jpg", 4L, | |
| 75 PickerBitmap.PICTURE)); mTestFiles.add(new | |
| 76 PickerBitmap("/storage/emulated/0/DCIM/Camera/IMG_20170201_154707.jpg", 3L, | |
| 77 PickerBitmap.PICTURE)); mTestFiles.add(new | |
| 78 PickerBitmap("/storage/emulated/0/DCIM/Camera/IMG_20170201_154709.jpg", 2L, | |
| 79 PickerBitmap.PICTURE)); mTestFiles.add(new | |
| 80 PickerBitmap("/storage/emulated/0/DCIM/Camera/IMG_20170201_154711.jpg", 1L, | |
| 81 PickerBitmap.PICTURE)); mTestFiles.add(new | |
| 82 PickerBitmap("/storage/emulated/0/DCIM/Camera/IMG_20170201_154714.jpg", 0L, | |
| 83 PickerBitmap.PICTURE)); | |
| 84 */ | |
| 85 } | |
| 86 | |
| 87 @Override | |
| 88 public void startMainActivity() throws InterruptedException { | |
| 89 startMainActivityOnBlankPage(); | |
| 90 } | |
| 91 | |
| 92 // PhotoPickerDialog.PhotoPickerListener: | |
| 93 | |
| 94 @Override | |
| 95 public void onPickerUserAction(Action action, String[] photos) { | |
| 96 mLastActionRecorded = action; | |
| 97 mLastSelectedPhotos = photos; | |
| 98 if (mLastSelectedPhotos != null) Arrays.sort(mLastSelectedPhotos); | |
| 99 } | |
| 100 | |
| 101 // SelectionObserver: | |
| 102 | |
| 103 @Override | |
| 104 public void onSelectionStateChange(List<PickerBitmap> photosSelected) { | |
| 105 mCurrentPhotoSelection = new ArrayList<>(photosSelected); | |
| 106 } | |
| 107 | |
| 108 private RecyclerView recyclerView() { | |
| 109 return (RecyclerView) mDialog.findViewById(R.id.recycler_view); | |
| 110 } | |
| 111 | |
| 112 private PhotoPickerDialog createDialog(final boolean multiselect) { | |
| 113 final PhotoPickerDialog dialog = | |
| 114 ThreadUtils.runOnUiThreadBlockingNoException(new Callable<PhotoP ickerDialog>() { | |
| 115 @Override | |
| 116 public PhotoPickerDialog call() { | |
| 117 final PhotoPickerDialog dialog = new PhotoPickerDialog( | |
| 118 getActivity(), PhotoPickerDialogTest.this, multi select, mTestFiles); | |
| 119 dialog.show(); | |
| 120 return dialog; | |
| 121 } | |
| 122 }); | |
| 123 | |
| 124 SelectionDelegate<PickerBitmap> selectionDelegate = | |
| 125 dialog.getCategoryViewForTesting().getSelectionDelegateForTestin g(); | |
| 126 if (!multiselect) selectionDelegate.setSingleSelectionMode(); | |
| 127 selectionDelegate.addObserver(this); | |
| 128 | |
| 129 return dialog; | |
| 130 } | |
| 131 | |
| 132 public void waitForRecyclerToStart() { | |
| 133 CriteriaHelper.pollUiThread(new Criteria() { | |
|
Theresa
2017/05/19 16:52:42
Where possible, it's preferable to rely on specifi
Finnur
2017/05/23 13:19:51
Not all of the polling turned out to be necessary;
| |
| 134 @Override | |
| 135 public boolean isSatisfied() { | |
| 136 RecyclerView recyclerView = recyclerView(); | |
| 137 return recyclerView != null && recyclerView.getChildCount() > 0; | |
| 138 } | |
| 139 }); | |
| 140 } | |
| 141 | |
| 142 public void waitForViewToStartLoading(int position) { | |
| 143 final PickerBitmapViewHolder holder = | |
| 144 (PickerBitmapViewHolder) RecyclerViewTestUtils.waitForView( | |
| 145 recyclerView(), position); | |
| 146 | |
| 147 CriteriaHelper.pollUiThread(new Criteria() { | |
| 148 @Override | |
| 149 public boolean isSatisfied() { | |
| 150 return holder.getImageLoadingForTesting(); | |
| 151 } | |
| 152 }); | |
| 153 } | |
| 154 | |
| 155 public void clickView(final int position, final int expectedSelectionCount) { | |
| 156 waitForViewToStartLoading(position); | |
| 157 | |
| 158 RecyclerView recyclerView = recyclerView(); | |
| 159 TouchCommon.singleClickView( | |
| 160 recyclerView.findViewHolderForAdapterPosition(position).itemView ); | |
| 161 | |
| 162 CriteriaHelper.pollUiThread(new Criteria() { | |
|
Theresa
2017/05/19 16:52:42
This is waiting for the view to be selected, corre
Finnur
2017/05/23 13:19:50
Done.
| |
| 163 @Override | |
| 164 public boolean isSatisfied() { | |
| 165 if (mCurrentPhotoSelection == null | |
| 166 || mCurrentPhotoSelection.size() != expectedSelectionCou nt) { | |
| 167 return false; | |
| 168 } | |
| 169 | |
| 170 for (int i = 0; i < mCurrentPhotoSelection.size(); ++i) { | |
| 171 if (mCurrentPhotoSelection.get(i).getFilePath().equals( | |
| 172 mTestFiles.get(position).getFilePath())) { | |
| 173 return true; | |
| 174 } | |
| 175 } | |
| 176 return false; | |
| 177 } | |
| 178 }); | |
| 179 } | |
| 180 | |
| 181 public void clickDone() { | |
| 182 mLastActionRecorded = null; | |
| 183 | |
| 184 PhotoPickerToolbar toolbar = (PhotoPickerToolbar) mDialog.findViewById(R .id.action_bar); | |
| 185 Button done = (Button) toolbar.findViewById(R.id.done); | |
| 186 TouchCommon.singleClickView(done); | |
| 187 | |
| 188 CriteriaHelper.pollUiThread(new Criteria() { | |
|
Theresa
2017/05/19 16:52:42
Instead of polling the UI thread, you should be ab
Finnur
2017/05/23 13:19:51
Done.
| |
| 189 @Override | |
| 190 public boolean isSatisfied() { | |
| 191 return mLastActionRecorded != null; | |
| 192 } | |
| 193 }); | |
| 194 } | |
| 195 | |
| 196 public void clickCancel() { | |
| 197 mLastActionRecorded = null; | |
| 198 | |
| 199 PickerCategoryView categoryView = mDialog.getCategoryViewForTesting(); | |
| 200 View cancel = new View(getActivity()); | |
| 201 categoryView.onClick(cancel); | |
| 202 | |
| 203 CriteriaHelper.pollUiThread(new Criteria() { | |
| 204 @Override | |
| 205 public boolean isSatisfied() { | |
| 206 return mLastActionRecorded != null; | |
| 207 } | |
| 208 }); | |
| 209 } | |
| 210 | |
| 211 @LargeTest | |
| 212 public void testNoSelection() throws Throwable { | |
| 213 mDialog = createDialog(false); // Multi-select = false. | |
| 214 waitForRecyclerToStart(); | |
| 215 assertTrue(mDialog.isShowing()); | |
| 216 | |
| 217 clickCancel(); | |
| 218 | |
| 219 assertEquals(null, mLastSelectedPhotos); | |
| 220 assertEquals(PhotoPickerListener.Action.CANCEL, mLastActionRecorded); | |
| 221 | |
| 222 mDialog.dismiss(); | |
| 223 } | |
| 224 | |
| 225 @LargeTest | |
| 226 public void testSingleSelectionPhoto() throws Throwable { | |
| 227 mDialog = createDialog(false); // Multi-select = false. | |
| 228 waitForRecyclerToStart(); | |
| 229 assertTrue(mDialog.isShowing()); | |
| 230 | |
| 231 // Expected selection count is 1 because clicking on a new view unselect s other. | |
| 232 int expectedSelectionCount = 1; | |
| 233 clickView(0, expectedSelectionCount); | |
| 234 clickView(1, expectedSelectionCount); | |
| 235 clickDone(); | |
| 236 | |
| 237 assertEquals(1, mLastSelectedPhotos.length); | |
| 238 assertEquals(PhotoPickerListener.Action.PHOTOS_SELECTED, mLastActionReco rded); | |
| 239 assertEquals(mTestFiles.get(1).getFilePath(), mLastSelectedPhotos[0]); | |
| 240 | |
| 241 mDialog.dismiss(); | |
| 242 } | |
| 243 | |
| 244 @LargeTest | |
| 245 public void testMultiSelectionPhoto() throws Throwable { | |
| 246 mDialog = createDialog(true); // Multi-select = true. | |
| 247 waitForRecyclerToStart(); | |
| 248 assertTrue(mDialog.isShowing()); | |
| 249 | |
| 250 // Multi-selection is enabled, so each click is counted. | |
| 251 int expectedSelectionCount = 1; | |
| 252 clickView(0, expectedSelectionCount++); | |
| 253 clickView(2, expectedSelectionCount++); | |
| 254 clickView(4, expectedSelectionCount++); | |
| 255 clickDone(); | |
| 256 | |
| 257 assertEquals(3, mLastSelectedPhotos.length); | |
| 258 assertEquals(PhotoPickerListener.Action.PHOTOS_SELECTED, mLastActionReco rded); | |
| 259 assertEquals(mTestFiles.get(0).getFilePath(), mLastSelectedPhotos[0]); | |
| 260 assertEquals(mTestFiles.get(2).getFilePath(), mLastSelectedPhotos[1]); | |
| 261 assertEquals(mTestFiles.get(4).getFilePath(), mLastSelectedPhotos[2]); | |
| 262 | |
| 263 mDialog.dismiss(); | |
| 264 } | |
| 265 } | |
| OLD | NEW |