1 /* 2 * Copyright (C) 2019 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 package com.android.wallpaper.picker.individual; 17 18 import static androidx.test.espresso.Espresso.onView; 19 import static androidx.test.espresso.action.ViewActions.click; 20 import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; 21 import static androidx.test.espresso.assertion.ViewAssertions.matches; 22 import static androidx.test.espresso.intent.Intents.intending; 23 import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; 24 import static androidx.test.espresso.matcher.RootMatchers.isDialog; 25 import static androidx.test.espresso.matcher.ViewMatchers.isChecked; 26 import static androidx.test.espresso.matcher.ViewMatchers.isClickable; 27 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; 28 import static androidx.test.espresso.matcher.ViewMatchers.withId; 29 import static androidx.test.espresso.matcher.ViewMatchers.withText; 30 31 import static junit.framework.TestCase.assertFalse; 32 33 import static org.junit.Assert.assertEquals; 34 import static org.junit.Assert.assertNotNull; 35 import static org.junit.Assert.assertNull; 36 import static org.junit.Assert.assertTrue; 37 38 import android.app.Activity; 39 import android.app.Instrumentation.ActivityResult; 40 import android.app.WallpaperManager; 41 import android.content.Context; 42 import android.content.Intent; 43 44 import androidx.recyclerview.widget.RecyclerView; 45 import androidx.test.espresso.intent.Intents; 46 import androidx.test.filters.MediumTest; 47 import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner; 48 import androidx.test.platform.app.InstrumentationRegistry; 49 import androidx.test.rule.ActivityTestRule; 50 51 import com.android.wallpaper.R; 52 import com.android.wallpaper.model.Category; 53 import com.android.wallpaper.model.PickerIntentFactory; 54 import com.android.wallpaper.model.WallpaperInfo; 55 import com.android.wallpaper.model.WallpaperRotationInitializer; 56 import com.android.wallpaper.model.WallpaperRotationInitializer.RotationInitializationState; 57 import com.android.wallpaper.module.Injector; 58 import com.android.wallpaper.module.InjectorProvider; 59 import com.android.wallpaper.testing.TestCategoryProvider; 60 import com.android.wallpaper.testing.TestFormFactorChecker; 61 import com.android.wallpaper.testing.TestInjector; 62 import com.android.wallpaper.testing.TestWallpaperCategory; 63 import com.android.wallpaper.testing.TestWallpaperInfo; 64 import com.android.wallpaper.testing.TestWallpaperPreferences; 65 import com.android.wallpaper.testing.TestWallpaperRotationInitializer; 66 67 import org.hamcrest.Matcher; 68 import org.junit.After; 69 import org.junit.Before; 70 import org.junit.Rule; 71 import org.junit.Test; 72 import org.junit.runner.RunWith; 73 74 import java.util.ArrayList; 75 import java.util.Arrays; 76 import java.util.List; 77 78 /** 79 * Tests for {@link IndividualPickerActivity}. 80 */ 81 @RunWith(AndroidJUnit4ClassRunner.class) 82 @MediumTest 83 public class IndividualPickerActivityTest { 84 85 private static final String EXTRA_WALLPAPER_INFO = 86 "com.android.wallpaper.picker.wallpaper_info"; 87 private static final TestWallpaperInfo sWallpaperInfo1 = new TestWallpaperInfo( 88 TestWallpaperInfo.COLOR_BLACK, "test-wallpaper-1"); 89 private static final TestWallpaperInfo sWallpaperInfo2 = new TestWallpaperInfo( 90 TestWallpaperInfo.COLOR_BLACK, "test-wallpaper-2"); 91 private static final TestWallpaperInfo sWallpaperInfo3 = new TestWallpaperInfo( 92 TestWallpaperInfo.COLOR_BLACK, "test-wallpaper-3"); 93 94 private TestCategoryProvider mTestCategoryProvider; 95 96 private TestFormFactorChecker mTestFormFactorChecker; 97 private Injector mInjector; 98 99 private TestWallpaperCategory mTestCategory; 100 101 private TestWallpaperPreferences mPreferences; 102 private ArrayList<WallpaperInfo> mWallpapers; 103 104 @Rule 105 public ActivityTestRule<IndividualPickerActivity> mActivityRule = 106 new ActivityTestRule<>(IndividualPickerActivity.class, false, false); 107 108 @Before setUp()109 public void setUp() { 110 Intents.init(); 111 112 mInjector = new TestInjector(); 113 InjectorProvider.setInjector(mInjector); 114 115 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 116 mTestFormFactorChecker = (TestFormFactorChecker) mInjector.getFormFactorChecker(context); 117 mTestCategoryProvider = (TestCategoryProvider) mInjector.getCategoryProvider(context); 118 119 sWallpaperInfo1.setAttributions(Arrays.asList( 120 "Attribution 0", "Attribution 1", "Attribution 2")); 121 122 sWallpaperInfo1.setCollectionId("collection"); 123 124 mPreferences = (TestWallpaperPreferences) mInjector.getPreferences(context); 125 126 mWallpapers = new ArrayList<>(); 127 mWallpapers.add(sWallpaperInfo1); 128 mWallpapers.add(sWallpaperInfo2); 129 mWallpapers.add(sWallpaperInfo3); 130 } 131 132 @After tearDown()133 public void tearDown() { 134 Intents.release(); 135 mActivityRule.finishActivity(); 136 } 137 getActivity()138 private IndividualPickerActivity getActivity() { 139 return mActivityRule.getActivity(); 140 } 141 setUpFragmentForTesting()142 private void setUpFragmentForTesting() { 143 IndividualPickerFragment fragment = (IndividualPickerFragment) 144 getActivity().getSupportFragmentManager().findFragmentById(R.id.fragment_container); 145 fragment.setTestingMode(true); 146 } 147 setActivityWithMockWallpapers(boolean isRotationEnabled, @RotationInitializationState int rotationState)148 private void setActivityWithMockWallpapers(boolean isRotationEnabled, 149 @RotationInitializationState int rotationState) { 150 mTestCategory = new TestWallpaperCategory( 151 "Test category", "collection", mWallpapers, 0 /* priority */); 152 mTestCategory.setIsRotationEnabled(isRotationEnabled); 153 mTestCategory.setRotationInitializationState(rotationState); 154 155 List<Category> testCategories = mTestCategoryProvider.getTestCategories(); 156 testCategories.set(0, mTestCategory); 157 158 PickerIntentFactory intentFactory = 159 new IndividualPickerActivity.IndividualPickerActivityIntentFactory(); 160 Intent intent = intentFactory.newIntent( 161 InstrumentationRegistry.getInstrumentation().getTargetContext(), 162 mTestCategory.getCollectionId()); 163 mActivityRule.launchActivity(intent); 164 } 165 166 @Test testDrawsTilesForProvidedWallpapers()167 public void testDrawsTilesForProvidedWallpapers() { 168 setActivityWithMockWallpapers(false /* isRotationEnabled */, 169 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 170 IndividualPickerActivity activity = getActivity(); 171 172 RecyclerView recyclerView = activity.findViewById(R.id.wallpaper_grid); 173 174 // There are only three wallpapers in the category, so the grid should only have three 175 // items. 176 assertNotNull(recyclerView.findViewHolderForAdapterPosition(0)); 177 assertNotNull(recyclerView.findViewHolderForAdapterPosition(1)); 178 assertNotNull(recyclerView.findViewHolderForAdapterPosition(2)); 179 assertNull(recyclerView.findViewHolderForAdapterPosition(3)); 180 } 181 182 @Test testClickDailyRefreshAction_ShowsStartRotationDialog()183 public void testClickDailyRefreshAction_ShowsStartRotationDialog() { 184 setActivityWithMockWallpapers(true /* isRotationEnabled */, 185 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 186 getActivity(); 187 188 onView(withId(R.id.action_rotation)).perform(click()); 189 190 onView(withId(R.id.start_rotation_wifi_only_checkbox)) 191 .check(matches(isDisplayed())); 192 // WiFi-only option should be checked by default. 193 onView(withId(R.id.start_rotation_wifi_only_checkbox)) 194 .check(matches(isChecked())); 195 } 196 197 @Test testStartRotationDialogUiComponents()198 public void testStartRotationDialogUiComponents() { 199 setActivityWithMockWallpapers(true /* isRotationEnabled */, 200 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 201 getActivity(); 202 203 onView(withId(R.id.action_rotation)).perform(click()); 204 205 onView(withText(R.string.start_rotation_dialog_body)).check(matches(isDisplayed())); 206 onView(withText(android.R.string.cancel)).check(matches(isDisplayed())); 207 onView(withText(android.R.string.cancel)).check(matches(isClickable())); 208 onView(withText(android.R.string.ok)).check(matches(isDisplayed())); 209 onView(withText(android.R.string.ok)).check(matches(isClickable())); 210 onView(withId(R.id.start_rotation_wifi_only_checkbox)) 211 .check(matches(isDisplayed())); 212 onView(withId(R.id.start_rotation_wifi_only_checkbox)) 213 .check(matches(isClickable())); 214 onView(withText(R.string.start_rotation_dialog_wifi_only_option_message)) 215 .check(matches(isDisplayed())); 216 } 217 218 @Test testShowStartRotationDialog_WifiOnly_ClickOK_StartsRotation()219 public void testShowStartRotationDialog_WifiOnly_ClickOK_StartsRotation() throws Throwable { 220 setActivityWithMockWallpapers(true /* isRotationEnabled */, 221 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 222 getActivity(); 223 224 setUpFragmentForTesting(); 225 TestWallpaperRotationInitializer 226 testWPRotationInitializer = (TestWallpaperRotationInitializer) 227 mTestCategory.getWallpaperRotationInitializer(); 228 assertFalse(testWPRotationInitializer.isRotationInitialized()); 229 230 // Mock out the intent and response for the live wallpaper preview. 231 Matcher<Intent> expectedIntent = hasAction(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER); 232 intending(expectedIntent).respondWith(new ActivityResult(Activity.RESULT_OK, null)); 233 234 onView(withId(R.id.action_rotation)).perform(click()); 235 236 onView(withText(android.R.string.ok)).perform(click()); 237 mActivityRule.runOnUiThread(() -> { 238 testWPRotationInitializer.finishDownloadingFirstWallpaper(true /* isSuccessful */); 239 assertTrue(testWPRotationInitializer.isRotationInitialized()); 240 assertTrue(testWPRotationInitializer.isWifiOnly()); 241 242 // The activity should finish if starting a rotation was successful. 243 assertTrue(getActivity().isFinishing()); 244 }); 245 } 246 247 @Test testShowStartRotationDialog_WifiOnly_ClickOK_Fails_ShowsErrorDialog()248 public void testShowStartRotationDialog_WifiOnly_ClickOK_Fails_ShowsErrorDialog() { 249 setActivityWithMockWallpapers(true /* isRotationEnabled */, 250 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 251 getActivity(); 252 253 setUpFragmentForTesting(); 254 TestWallpaperRotationInitializer 255 testWPRotationInitializer = (TestWallpaperRotationInitializer) 256 mTestCategory.getWallpaperRotationInitializer(); 257 assertFalse(testWPRotationInitializer.isRotationInitialized()); 258 259 onView(withId(R.id.action_rotation)).perform(click()); 260 onView(withText(android.R.string.ok)).perform(click()); 261 262 testWPRotationInitializer.finishDownloadingFirstWallpaper(false /* isSuccessful */); 263 assertFalse(testWPRotationInitializer.isRotationInitialized()); 264 265 // Error dialog should be shown with retry option. 266 onView(withText(R.string.start_rotation_error_message)) 267 .inRoot(isDialog()).check(matches(isDisplayed())); 268 onView(withText(R.string.try_again)) 269 .inRoot(isDialog()).check(matches(isDisplayed())); 270 } 271 272 @Test testStartRotation_WifiOnly_FailOnce_Retry()273 public void testStartRotation_WifiOnly_FailOnce_Retry() throws Throwable { 274 setActivityWithMockWallpapers(true /* isRotationEnabled */, 275 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 276 getActivity(); 277 278 setUpFragmentForTesting(); 279 TestWallpaperRotationInitializer 280 testWPRotationInitializer = (TestWallpaperRotationInitializer) 281 mTestCategory.getWallpaperRotationInitializer(); 282 assertFalse(testWPRotationInitializer.isRotationInitialized()); 283 284 onView(withId(R.id.action_rotation)).perform(click()); 285 onView(withText(android.R.string.ok)).perform(click()); 286 287 testWPRotationInitializer.finishDownloadingFirstWallpaper(false /* isSuccessful */); 288 assertFalse(testWPRotationInitializer.isRotationInitialized()); 289 290 // Click try again to retry. 291 onView(withText(R.string.try_again)).inRoot(isDialog()).perform(click()); 292 293 mActivityRule.runOnUiThread(() -> { 294 testWPRotationInitializer.finishDownloadingFirstWallpaper(true /* isSuccessful */); 295 assertTrue(testWPRotationInitializer.isRotationInitialized()); 296 assertTrue(testWPRotationInitializer.isWifiOnly()); 297 }); 298 } 299 300 @Test testShowStartRotationDialog_TurnOffWifiOnly_ClickOK_StartsRotation()301 public void testShowStartRotationDialog_TurnOffWifiOnly_ClickOK_StartsRotation() 302 throws Throwable { 303 setActivityWithMockWallpapers(true /* isRotationEnabled */, 304 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 305 getActivity(); 306 307 setUpFragmentForTesting(); 308 TestWallpaperRotationInitializer 309 testWPRotationInitializer = (TestWallpaperRotationInitializer) 310 mTestCategory.getWallpaperRotationInitializer(); 311 assertFalse(testWPRotationInitializer.isRotationInitialized()); 312 313 onView(withId(R.id.action_rotation)).perform(click()); 314 // Click on WiFi-only option to toggle it off. 315 onView(withId(R.id.start_rotation_wifi_only_checkbox)).perform(click()); 316 onView(withText(android.R.string.ok)).perform(click()); 317 318 mActivityRule.runOnUiThread(() -> { 319 testWPRotationInitializer.finishDownloadingFirstWallpaper(true /* isSuccessful */); 320 assertTrue(testWPRotationInitializer.isRotationInitialized()); 321 assertFalse(testWPRotationInitializer.isWifiOnly()); 322 }); 323 } 324 325 @Test testStartRotation_WifiOnly_FailOnce_Retry_ShouldStillHaveWifiTurnedOff()326 public void testStartRotation_WifiOnly_FailOnce_Retry_ShouldStillHaveWifiTurnedOff() 327 throws Throwable { 328 setActivityWithMockWallpapers(true /* isRotationEnabled */, 329 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 330 getActivity(); 331 332 setUpFragmentForTesting(); 333 TestWallpaperRotationInitializer 334 testWPRotationInitializer = (TestWallpaperRotationInitializer) 335 mTestCategory.getWallpaperRotationInitializer(); 336 assertFalse(testWPRotationInitializer.isRotationInitialized()); 337 338 onView(withId(R.id.action_rotation)).perform(click()); 339 // Click on WiFi-only option to toggle it off. 340 onView(withId(R.id.start_rotation_wifi_only_checkbox)).perform(click()); 341 onView(withText(android.R.string.ok)).perform(click()); 342 343 testWPRotationInitializer.finishDownloadingFirstWallpaper(false /* isSuccessful */); 344 assertFalse(testWPRotationInitializer.isRotationInitialized()); 345 346 // Click try again to retry. 347 onView(withText(R.string.try_again)).inRoot(isDialog()).perform(click()); 348 349 mActivityRule.runOnUiThread(() -> { 350 testWPRotationInitializer.finishDownloadingFirstWallpaper(true /* isSuccessful */); 351 assertTrue(testWPRotationInitializer.isRotationInitialized()); 352 assertFalse(testWPRotationInitializer.isWifiOnly()); 353 }); 354 } 355 356 @Test testShowStartRotationDialog_ClickCancel_DismissesDialog()357 public void testShowStartRotationDialog_ClickCancel_DismissesDialog() { 358 setActivityWithMockWallpapers(true /* isRotationEnabled */, 359 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 360 getActivity(); 361 362 setUpFragmentForTesting(); 363 TestWallpaperRotationInitializer 364 testWPRotationInitializer = (TestWallpaperRotationInitializer) 365 mTestCategory.getWallpaperRotationInitializer(); 366 assertFalse(testWPRotationInitializer.isRotationInitialized()); 367 368 onView(withId(R.id.action_rotation)).perform(click()); 369 onView(withId(R.id.start_rotation_wifi_only_checkbox)).check(matches(isDisplayed())); 370 // WiFi-only option should be checked by default. 371 onView(withId(R.id.start_rotation_wifi_only_checkbox)).check(matches(isChecked())); 372 373 // Click "Cancel" to dismiss the dialog. 374 onView(withText(android.R.string.cancel)).perform(click()); 375 376 // Rotation was not initialized and dialog is no longer visible. 377 assertFalse(testWPRotationInitializer.isRotationInitialized()); 378 onView(withId(R.id.start_rotation_wifi_only_checkbox)).check(doesNotExist()); 379 } 380 381 /** 382 * Tests that when no title is present, a wallpaper tile's content description attribute is 383 * set to the first attribution. 384 */ 385 @Test testWallpaperHasContentDescriptionFromAttribution()386 public void testWallpaperHasContentDescriptionFromAttribution() { 387 setActivityWithMockWallpapers(false /* isRotationEnabled */, 388 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 389 IndividualPickerActivity activity = getActivity(); 390 391 RecyclerView recyclerView = activity.findViewById(R.id.wallpaper_grid); 392 393 RecyclerView.ViewHolder holder = recyclerView.findViewHolderForAdapterPosition(0); 394 assertEquals("Attribution 0", holder.itemView.findViewById(R.id.tile) 395 .getContentDescription()); 396 } 397 398 /** 399 * Tests whether the selected wallpaper has a clipped thumbnail: first wallpaper. 400 */ 401 @Test testSelectFirstWallpaper_ShowsClippedThumbnail()402 public void testSelectFirstWallpaper_ShowsClippedThumbnail() { 403 runSelectWallpaperTest(0); 404 } 405 406 /** 407 * Tests whether the selected wallpaper has a clipped thumbnail: second wallpaper. 408 */ 409 @Test testSelectSecondWallpaper_ShowsClippedThumbnail()410 public void testSelectSecondWallpaper_ShowsClippedThumbnail() { 411 runSelectWallpaperTest(1); 412 } 413 414 /** 415 * Tests whether the selected wallpaper has a clipped thumbnail: third wallpaper. 416 */ 417 @Test testSelectThirdWallpaper_ShowsClippedThumbnail()418 public void testSelectThirdWallpaper_ShowsClippedThumbnail() { 419 runSelectWallpaperTest(2); 420 } 421 runSelectWallpaperTest(int selectedWallpaperIndex)422 private void runSelectWallpaperTest(int selectedWallpaperIndex) { 423 mPreferences.setHomeWallpaperRemoteId( 424 mWallpapers.get(selectedWallpaperIndex).getWallpaperId()); 425 426 setActivityWithMockWallpapers(false /* isRotationEnabled */, 427 WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED); 428 IndividualPickerActivity activity = getActivity(); 429 430 RecyclerView recyclerView = activity.findViewById(R.id.wallpaper_grid); 431 432 for (int index = 0; index < 3; index++) { 433 assertNotNull(recyclerView.findViewHolderForAdapterPosition(index)); 434 435 CustomShapeImageView thumbnail = 436 recyclerView.findViewHolderForAdapterPosition(index) 437 .itemView.findViewById(R.id.thumbnail); 438 439 // Assert that only the selected wallpaper has a clipped thumbnail. 440 assertEquals(thumbnail.getClipped(), index == selectedWallpaperIndex); 441 } 442 } 443 } 444