From e6f11ad0f2a8043804869dcfc03c735dd78ebf00 Mon Sep 17 00:00:00 2001 From: Yi-Ling Chuang Date: Tue, 22 Jan 2019 12:12:08 +0800 Subject: [PATCH] Add tests for ContextualCardManager. Bug: 114307549 Test: robotests Change-Id: Iac9450ed21011cb6e8186fbe686ff4d03547ba5e --- .../ContextualCardManager.java | 21 ++-- .../ContextualCardManagerTest.java | 107 ++++++++++++++++-- 2 files changed, 113 insertions(+), 15 deletions(-) diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java index 92108f0f535..d8361a9c495 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java @@ -72,26 +72,29 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo static final long CARD_CONTENT_LOADER_TIMEOUT_MS = DateUtils.SECOND_IN_MILLIS; @VisibleForTesting static final String KEY_GLOBAL_CARD_LOADER_TIMEOUT = "global_card_loader_timeout_key"; + @VisibleForTesting + static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards"; - private static final String KEY_CONTEXTUAL_CARDS = "key_contextual_cards"; private static final String TAG = "ContextualCardManager"; //The list for Settings Custom Card private static final int[] SETTINGS_CARDS = {ContextualCard.CardType.CONDITIONAL, ContextualCard.CardType.LEGACY_SUGGESTION}; - @VisibleForTesting - final List mContextualCards; private final Context mContext; private final ControllerRendererPool mControllerRendererPool; private final Lifecycle mLifecycle; private final List mLifecycleObservers; + private ContextualCardUpdateListener mListener; + + @VisibleForTesting + final List mContextualCards; @VisibleForTesting long mStartTime; + @VisibleForTesting boolean mIsFirstLaunch; @VisibleForTesting List mSavedCards; - private ContextualCardUpdateListener mListener; public ContextualCardManager(Context context, Lifecycle lifecycle, Bundle savedInstanceState) { mContext = context; @@ -128,7 +131,8 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo } } - private void setupController(@ContextualCard.CardType int cardType) { + @VisibleForTesting + void setupController(@ContextualCard.CardType int cardType) { final ContextualCardController controller = mControllerRendererPool.getController(mContext, cardType); if (controller == null) { @@ -211,7 +215,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); - final long timeoutLimit = getCardLoaderTimeout(mContext); + final long timeoutLimit = getCardLoaderTimeout(); if (loadTime <= timeoutLimit) { onContextualCardUpdated(cards.stream() .collect(groupingBy(ContextualCard::getCardType))); @@ -275,7 +279,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo } @VisibleForTesting - long getCardLoaderTimeout(Context context) { + long getCardLoaderTimeout() { // Return the timeout limit if Settings.Global has the KEY_GLOBAL_CARD_LOADER_TIMEOUT key, // else return default timeout. return Settings.Global.getLong(mContext.getContentResolver(), @@ -317,7 +321,8 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo return result; } - private List getCardsToKeep(List cards) { + @VisibleForTesting + List getCardsToKeep(List cards) { if (mSavedCards != null) { //screen rotate final List cardsToKeep = cards.stream() diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java index 8087716c9e1..9759f982da8 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java @@ -16,21 +16,25 @@ package com.android.settings.homepage.contextualcards; +import static com.android.settings.homepage.contextualcards.ContextualCardManager.KEY_CONTEXTUAL_CARDS; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.content.Context; import android.net.Uri; +import android.os.Bundle; import android.provider.Settings; import android.util.ArrayMap; @@ -39,6 +43,8 @@ import com.android.settings.homepage.contextualcards.conditional.ConditionHeader import com.android.settings.homepage.contextualcards.conditional.ConditionalContextualCard; import com.android.settings.intelligence.ContextualCardProto; import com.android.settings.slices.CustomSliceRegistry; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.core.lifecycle.LifecycleObserver; import org.junit.Before; import org.junit.Test; @@ -62,6 +68,8 @@ public class ContextualCardManagerTest { @Mock ContextualCardUpdateListener mListener; + @Mock + Lifecycle mLifecycle; private Context mContext; private ContextualCardManager mManager; @@ -70,9 +78,71 @@ public class ContextualCardManagerTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; - final ContextualCardsFragment fragment = new ContextualCardsFragment(); - mManager = new ContextualCardManager(mContext, fragment.getSettingsLifecycle(), - null /* bundle */); + mManager = new ContextualCardManager(mContext, mLifecycle, null /* bundle */); + } + + @Test + public void constructor_noSavedInstanceState_shouldSetFirstLaunch() { + assertThat(mManager.mIsFirstLaunch).isTrue(); + } + + @Test + public void constructor_noSavedInstanceState_shouldNotHaveSavedCards() { + assertThat(mManager.mSavedCards).isNull(); + } + + @Test + public void constructor_hasSavedInstanceState_shouldContainExpectedSavedCards() { + final Bundle outState = new Bundle(); + final ArrayList cards = getContextualCardList().stream() + .map(ContextualCard::getName) + .collect(Collectors.toCollection(ArrayList::new)); + outState.putStringArrayList(KEY_CONTEXTUAL_CARDS, cards); + + mManager = new ContextualCardManager(mContext, mLifecycle, outState); + + final List actualCards = mManager.mSavedCards.stream().collect(Collectors.toList()); + final List expectedCards = Arrays.asList("test_wifi", "test_flashlight", + "test_connected", "test_gesture", "test_battery"); + assertThat(actualCards).containsExactlyElementsIn(expectedCards); + } + + @Test + public void constructor_hasSettingsCustomCards_shouldSetUpCustomControllers() { + final ControllerRendererPool pool = mManager.getControllerRendererPool(); + + final List actual = pool.getControllers().stream() + .map(ContextualCardController::getCardType) + .collect(Collectors.toList()); + final List expected = Arrays.asList(ContextualCard.CardType.CONDITIONAL, + ContextualCard.CardType.LEGACY_SUGGESTION); + assertThat(actual).containsExactlyElementsIn(expected); + } + + @Test + public void setupController_notLifecycleObserverInstance_shouldNotAttachToLifecycle() { + // 3 invocations in constructor(ContextualCardManager, Conditional and LegacySuggestion) + verify(mLifecycle, times(3)).addObserver(any(LifecycleObserver.class)); + + mManager.setupController(ContextualCard.CardType.SLICE); + + // After 3 times call in the constructor, addObserver() shouldn't be called again. + verify(mLifecycle, times(3)).addObserver(any(LifecycleObserver.class)); + } + + @Test + public void sortCards_shouldBeDescendingOrder() { + final List cards = new ArrayList<>(); + final ContextualCard card1 = + buildContextualCard(TEST_SLICE_URI).mutate().setRankingScore(99.0).build(); + final ContextualCard card2 = + buildContextualCard("context://test/test2").mutate().setRankingScore(88.0).build(); + cards.add(card1); + cards.add(card2); + + final List sortedCards = mManager.sortCards(cards); + + assertThat(sortedCards.get(0).getSliceUri()).isEqualTo(Uri.parse(TEST_SLICE_URI)); } @Test @@ -128,7 +198,7 @@ public class ContextualCardManagerTest { @Test public void getCardLoaderTimeout_noConfiguredTimeout_shouldReturnDefaultTimeout() { - final long timeout = mManager.getCardLoaderTimeout(mContext); + final long timeout = mManager.getCardLoaderTimeout(); assertThat(timeout).isEqualTo(ContextualCardManager.CARD_CONTENT_LOADER_TIMEOUT_MS); } @@ -139,7 +209,7 @@ public class ContextualCardManagerTest { Settings.Global.putLong(mContext.getContentResolver(), ContextualCardManager.KEY_GLOBAL_CARD_LOADER_TIMEOUT, configuredTimeout); - final long timeout = mManager.getCardLoaderTimeout(mContext); + final long timeout = mManager.getCardLoaderTimeout(); assertThat(timeout).isEqualTo(configuredTimeout); } @@ -151,6 +221,7 @@ public class ContextualCardManagerTest { doNothing().when(manager).onContextualCardUpdated(anyMap()); manager.onFinishCardLoading(new ArrayList<>()); + verify(manager).onContextualCardUpdated(nullable(Map.class)); } @@ -161,6 +232,7 @@ public class ContextualCardManagerTest { doNothing().when(manager).onContextualCardUpdated(anyMap()); manager.onFinishCardLoading(new ArrayList<>()); + verify(manager, never()).onContextualCardUpdated(anyMap()); } @@ -177,8 +249,18 @@ public class ContextualCardManagerTest { assertThat(mManager.mContextualCards).hasSize(2); } + @Test + public void onFinishCardLoading_newLaunch_shouldSetIsFirstLaunchBackToFalse() { + assertThat(mManager.mIsFirstLaunch).isTrue(); + + mManager.onFinishCardLoading(new ArrayList<>()); + + assertThat(mManager.mIsFirstLaunch).isFalse(); + } + @Test public void onFinishCardLoading_hasSavedCard_shouldOnlyShowSavedCard() { + // test screen rotation mManager.setListener(mListener); final List savedCardNames = new ArrayList<>(); savedCardNames.add(TEST_SLICE_NAME); @@ -204,7 +286,8 @@ public class ContextualCardManagerTest { } @Test - public void onFinishCardLoading_reloadData_shouldOnlyShowOldCard() { + public void onFinishCardLoading_reloadData_hasNewCard_shouldOnlyShowOldCard() { + // test card dismissal cases mManager.setListener(mListener); mManager.mIsFirstLaunch = false; //old card @@ -228,7 +311,6 @@ public class ContextualCardManagerTest { assertThat(actualCards).containsExactlyElementsIn(expectedCards); } - @Test public void getCardsWithViewType_noSuggestionCards_shouldNotHaveHalfCards() { final List categories = Arrays.asList( @@ -411,6 +493,17 @@ public class ContextualCardManagerTest { } } + @Test + public void getCardsToKeep_hasSavedCard_shouldResetSavedCards() { + final List savedCardNames = new ArrayList<>(); + savedCardNames.add(TEST_SLICE_NAME); + mManager.mSavedCards = savedCardNames; + + mManager.getCardsToKeep(getContextualCardList()); + + assertThat(mManager.mSavedCards).isNull(); + } + private ContextualCard buildContextualCard(String sliceUri) { return new ContextualCard.Builder() .setName(TEST_SLICE_NAME)