Merge "Add tests for ContextualCardManager."

This commit is contained in:
TreeHugger Robot
2019-04-03 22:07:38 +00:00
committed by Android (Google) Code Review
2 changed files with 113 additions and 15 deletions

View File

@@ -72,26 +72,29 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
static final long CARD_CONTENT_LOADER_TIMEOUT_MS = DateUtils.SECOND_IN_MILLIS; static final long CARD_CONTENT_LOADER_TIMEOUT_MS = DateUtils.SECOND_IN_MILLIS;
@VisibleForTesting @VisibleForTesting
static final String KEY_GLOBAL_CARD_LOADER_TIMEOUT = "global_card_loader_timeout_key"; 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"; private static final String TAG = "ContextualCardManager";
//The list for Settings Custom Card //The list for Settings Custom Card
private static final int[] SETTINGS_CARDS = private static final int[] SETTINGS_CARDS =
{ContextualCard.CardType.CONDITIONAL, ContextualCard.CardType.LEGACY_SUGGESTION}; {ContextualCard.CardType.CONDITIONAL, ContextualCard.CardType.LEGACY_SUGGESTION};
@VisibleForTesting
final List<ContextualCard> mContextualCards;
private final Context mContext; private final Context mContext;
private final ControllerRendererPool mControllerRendererPool; private final ControllerRendererPool mControllerRendererPool;
private final Lifecycle mLifecycle; private final Lifecycle mLifecycle;
private final List<LifecycleObserver> mLifecycleObservers; private final List<LifecycleObserver> mLifecycleObservers;
private ContextualCardUpdateListener mListener;
@VisibleForTesting
final List<ContextualCard> mContextualCards;
@VisibleForTesting @VisibleForTesting
long mStartTime; long mStartTime;
@VisibleForTesting
boolean mIsFirstLaunch; boolean mIsFirstLaunch;
@VisibleForTesting @VisibleForTesting
List<String> mSavedCards; List<String> mSavedCards;
private ContextualCardUpdateListener mListener;
public ContextualCardManager(Context context, Lifecycle lifecycle, Bundle savedInstanceState) { public ContextualCardManager(Context context, Lifecycle lifecycle, Bundle savedInstanceState) {
mContext = context; 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, final ContextualCardController controller = mControllerRendererPool.getController(mContext,
cardType); cardType);
if (controller == null) { if (controller == null) {
@@ -211,7 +215,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
final MetricsFeatureProvider metricsFeatureProvider = final MetricsFeatureProvider metricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
final long timeoutLimit = getCardLoaderTimeout(mContext); final long timeoutLimit = getCardLoaderTimeout();
if (loadTime <= timeoutLimit) { if (loadTime <= timeoutLimit) {
onContextualCardUpdated(cards.stream() onContextualCardUpdated(cards.stream()
.collect(groupingBy(ContextualCard::getCardType))); .collect(groupingBy(ContextualCard::getCardType)));
@@ -275,7 +279,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
} }
@VisibleForTesting @VisibleForTesting
long getCardLoaderTimeout(Context context) { long getCardLoaderTimeout() {
// Return the timeout limit if Settings.Global has the KEY_GLOBAL_CARD_LOADER_TIMEOUT key, // Return the timeout limit if Settings.Global has the KEY_GLOBAL_CARD_LOADER_TIMEOUT key,
// else return default timeout. // else return default timeout.
return Settings.Global.getLong(mContext.getContentResolver(), return Settings.Global.getLong(mContext.getContentResolver(),
@@ -317,7 +321,8 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
return result; return result;
} }
private List<ContextualCard> getCardsToKeep(List<ContextualCard> cards) { @VisibleForTesting
List<ContextualCard> getCardsToKeep(List<ContextualCard> cards) {
if (mSavedCards != null) { if (mSavedCards != null) {
//screen rotate //screen rotate
final List<ContextualCard> cardsToKeep = cards.stream() final List<ContextualCard> cardsToKeep = cards.stream()

View File

@@ -16,21 +16,25 @@
package com.android.settings.homepage.contextualcards; 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_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_FULL_WIDTH;
import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH; import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH;
import static com.google.common.truth.Truth.assertThat; 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.anyMap;
import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.util.ArrayMap; 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.homepage.contextualcards.conditional.ConditionalContextualCard;
import com.android.settings.intelligence.ContextualCardProto; import com.android.settings.intelligence.ContextualCardProto;
import com.android.settings.slices.CustomSliceRegistry; 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.Before;
import org.junit.Test; import org.junit.Test;
@@ -62,6 +68,8 @@ public class ContextualCardManagerTest {
@Mock @Mock
ContextualCardUpdateListener mListener; ContextualCardUpdateListener mListener;
@Mock
Lifecycle mLifecycle;
private Context mContext; private Context mContext;
private ContextualCardManager mManager; private ContextualCardManager mManager;
@@ -70,9 +78,71 @@ public class ContextualCardManagerTest {
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application; mContext = RuntimeEnvironment.application;
final ContextualCardsFragment fragment = new ContextualCardsFragment(); mManager = new ContextualCardManager(mContext, mLifecycle, null /* bundle */);
mManager = new ContextualCardManager(mContext, fragment.getSettingsLifecycle(), }
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<String> 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<String> actualCards = mManager.mSavedCards.stream().collect(Collectors.toList());
final List<String> 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<Integer> actual = pool.getControllers().stream()
.map(ContextualCardController::getCardType)
.collect(Collectors.toList());
final List<Integer> 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<ContextualCard> 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<ContextualCard> sortedCards = mManager.sortCards(cards);
assertThat(sortedCards.get(0).getSliceUri()).isEqualTo(Uri.parse(TEST_SLICE_URI));
} }
@Test @Test
@@ -128,7 +198,7 @@ public class ContextualCardManagerTest {
@Test @Test
public void getCardLoaderTimeout_noConfiguredTimeout_shouldReturnDefaultTimeout() { 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); assertThat(timeout).isEqualTo(ContextualCardManager.CARD_CONTENT_LOADER_TIMEOUT_MS);
} }
@@ -139,7 +209,7 @@ public class ContextualCardManagerTest {
Settings.Global.putLong(mContext.getContentResolver(), Settings.Global.putLong(mContext.getContentResolver(),
ContextualCardManager.KEY_GLOBAL_CARD_LOADER_TIMEOUT, configuredTimeout); ContextualCardManager.KEY_GLOBAL_CARD_LOADER_TIMEOUT, configuredTimeout);
final long timeout = mManager.getCardLoaderTimeout(mContext); final long timeout = mManager.getCardLoaderTimeout();
assertThat(timeout).isEqualTo(configuredTimeout); assertThat(timeout).isEqualTo(configuredTimeout);
} }
@@ -151,6 +221,7 @@ public class ContextualCardManagerTest {
doNothing().when(manager).onContextualCardUpdated(anyMap()); doNothing().when(manager).onContextualCardUpdated(anyMap());
manager.onFinishCardLoading(new ArrayList<>()); manager.onFinishCardLoading(new ArrayList<>());
verify(manager).onContextualCardUpdated(nullable(Map.class)); verify(manager).onContextualCardUpdated(nullable(Map.class));
} }
@@ -161,6 +232,7 @@ public class ContextualCardManagerTest {
doNothing().when(manager).onContextualCardUpdated(anyMap()); doNothing().when(manager).onContextualCardUpdated(anyMap());
manager.onFinishCardLoading(new ArrayList<>()); manager.onFinishCardLoading(new ArrayList<>());
verify(manager, never()).onContextualCardUpdated(anyMap()); verify(manager, never()).onContextualCardUpdated(anyMap());
} }
@@ -177,8 +249,18 @@ public class ContextualCardManagerTest {
assertThat(mManager.mContextualCards).hasSize(2); assertThat(mManager.mContextualCards).hasSize(2);
} }
@Test
public void onFinishCardLoading_newLaunch_shouldSetIsFirstLaunchBackToFalse() {
assertThat(mManager.mIsFirstLaunch).isTrue();
mManager.onFinishCardLoading(new ArrayList<>());
assertThat(mManager.mIsFirstLaunch).isFalse();
}
@Test @Test
public void onFinishCardLoading_hasSavedCard_shouldOnlyShowSavedCard() { public void onFinishCardLoading_hasSavedCard_shouldOnlyShowSavedCard() {
// test screen rotation
mManager.setListener(mListener); mManager.setListener(mListener);
final List<String> savedCardNames = new ArrayList<>(); final List<String> savedCardNames = new ArrayList<>();
savedCardNames.add(TEST_SLICE_NAME); savedCardNames.add(TEST_SLICE_NAME);
@@ -204,7 +286,8 @@ public class ContextualCardManagerTest {
} }
@Test @Test
public void onFinishCardLoading_reloadData_shouldOnlyShowOldCard() { public void onFinishCardLoading_reloadData_hasNewCard_shouldOnlyShowOldCard() {
// test card dismissal cases
mManager.setListener(mListener); mManager.setListener(mListener);
mManager.mIsFirstLaunch = false; mManager.mIsFirstLaunch = false;
//old card //old card
@@ -228,7 +311,6 @@ public class ContextualCardManagerTest {
assertThat(actualCards).containsExactlyElementsIn(expectedCards); assertThat(actualCards).containsExactlyElementsIn(expectedCards);
} }
@Test @Test
public void getCardsWithViewType_noSuggestionCards_shouldNotHaveHalfCards() { public void getCardsWithViewType_noSuggestionCards_shouldNotHaveHalfCards() {
final List<Integer> categories = Arrays.asList( final List<Integer> categories = Arrays.asList(
@@ -411,6 +493,17 @@ public class ContextualCardManagerTest {
} }
} }
@Test
public void getCardsToKeep_hasSavedCard_shouldResetSavedCards() {
final List<String> savedCardNames = new ArrayList<>();
savedCardNames.add(TEST_SLICE_NAME);
mManager.mSavedCards = savedCardNames;
mManager.getCardsToKeep(getContextualCardList());
assertThat(mManager.mSavedCards).isNull();
}
private ContextualCard buildContextualCard(String sliceUri) { private ContextualCard buildContextualCard(String sliceUri) {
return new ContextualCard.Builder() return new ContextualCard.Builder()
.setName(TEST_SLICE_NAME) .setName(TEST_SLICE_NAME)