Merge "Add tests for ContextualCardManager."
This commit is contained in:
committed by
Android (Google) Code Review
commit
d4f24dd9a9
@@ -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()
|
||||||
|
@@ -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)
|
||||||
|
Reference in New Issue
Block a user