Merge "Remove suggestion UI v1 codes."

This commit is contained in:
TreeHugger Robot
2018-01-31 21:15:18 +00:00
committed by Android (Google) Code Review
29 changed files with 746 additions and 3114 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,8 @@
package com.android.settings.dashboard;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -30,14 +28,14 @@ import static org.mockito.Mockito.when;
import android.app.PendingIntent;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.service.settings.suggestions.Suggestion;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
@@ -47,7 +45,6 @@ import com.android.settings.dashboard.suggestions.SuggestionAdapter;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
import org.junit.Before;
@@ -58,6 +55,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@@ -81,8 +79,6 @@ public class DashboardAdapterTest {
private Resources mResources;
private FakeFeatureFactory mFactory;
private DashboardAdapter mDashboardAdapter;
private DashboardAdapter.SuggestionAndConditionHeaderHolder mSuggestionHolder;
private DashboardData.SuggestionConditionHeaderData mSuggestionHeaderData;
private List<Condition> mConditionList;
@Before
@@ -98,30 +94,17 @@ public class DashboardAdapterTest {
mConditionList = new ArrayList<>();
mConditionList.add(mCondition);
when(mCondition.shouldShow()).thenReturn(true);
mDashboardAdapter = new DashboardAdapter(mContext, null, mConditionList, null, null);
mSuggestionHeaderData = new DashboardData.SuggestionConditionHeaderData(mConditionList, 1);
mDashboardAdapter = new DashboardAdapter(mContext, null /* savedInstanceState */,
mConditionList, null /* suggestionControllerMixin */, null /* lifecycle */);
when(mView.getTag()).thenReturn(mCondition);
}
@Test
public void testSuggestionsLogs_nullSuggestionsList_shouldNotCrash() {
setupSuggestions(makeSuggestionsV2("pkg1", "pkg2", "pkg3", "pkg4", "pkg5"));
mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData);
// set suggestions to null
final DashboardData prevData = mDashboardAdapter.mDashboardData;
mDashboardAdapter.mDashboardData = new DashboardData.Builder(prevData)
.setSuggestions(null)
.build();
mSuggestionHolder.itemView.callOnClick();
// no crash
}
@Test
public void testSuggestionDismissed_notOnlySuggestion_updateSuggestionOnly() {
final DashboardAdapter adapter =
spy(new DashboardAdapter(mContext, null, null, null, null));
spy(new DashboardAdapter(mContext, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /*
lifecycle */));
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1", "pkg2", "pkg3");
adapter.setSuggestions(suggestions);
@@ -130,18 +113,18 @@ public class DashboardAdapterTest {
when(data.getContext()).thenReturn(mContext);
when(mResources.getDisplayMetrics()).thenReturn(mock(DisplayMetrics.class));
final View itemView = mock(View.class);
when(itemView.findViewById(R.id.data)).thenReturn(data);
final DashboardAdapter.SuggestionAndConditionContainerHolder holder =
new DashboardAdapter.SuggestionAndConditionContainerHolder(itemView);
when(itemView.findViewById(R.id.suggestion_list)).thenReturn(data);
when(itemView.findViewById(android.R.id.summary)).thenReturn(mock(TextView.class));
final DashboardAdapter.SuggestionContainerHolder holder =
new DashboardAdapter.SuggestionContainerHolder(itemView);
adapter.onBindConditionAndSuggestion(
holder, DashboardAdapter.SUGGESTION_CONDITION_HEADER_POSITION);
adapter.onBindSuggestion(holder, 0);
final DashboardData dashboardData = adapter.mDashboardData;
reset(adapter); // clear interactions tracking
final Suggestion suggestionToRemove = suggestions.get(1);
adapter.onSuggestionDismissed(suggestionToRemove);
adapter.onSuggestionClosed(suggestionToRemove);
assertThat(adapter.mDashboardData).isEqualTo(dashboardData);
assertThat(suggestions.size()).isEqualTo(2);
@@ -150,25 +133,25 @@ public class DashboardAdapterTest {
}
@Test
public void testSuggestionDismissed_moreThanTwoSuggestions_defaultMode_shouldNotCrash() {
public void testSuggestionDismissed_moreThanTwoSuggestions_shouldNotCrash() {
final RecyclerView data = new RecyclerView(RuntimeEnvironment.application);
final View itemView = mock(View.class);
when(itemView.findViewById(R.id.data)).thenReturn(data);
final DashboardAdapter.SuggestionAndConditionContainerHolder holder =
new DashboardAdapter.SuggestionAndConditionContainerHolder(itemView);
when(itemView.findViewById(R.id.suggestion_list)).thenReturn(data);
when(itemView.findViewById(android.R.id.summary)).thenReturn(mock(TextView.class));
final DashboardAdapter.SuggestionContainerHolder holder =
new DashboardAdapter.SuggestionContainerHolder(itemView);
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1", "pkg2", "pkg3", "pkg4");
final DashboardAdapter adapter = spy(new DashboardAdapter(mContext, null /*savedInstance */,
null /* conditions */,
null /* suggestionControllerMixin */, null /* callback */));
final DashboardAdapter adapter = spy(new DashboardAdapter(mContext,
null /*savedInstance */, null /* conditions */,
null /* suggestionControllerMixin */,
null /* lifecycle */));
adapter.setSuggestions(suggestions);
adapter.onBindConditionAndSuggestion(
holder, DashboardAdapter.SUGGESTION_CONDITION_HEADER_POSITION);
// default mode, only displaying 2 suggestions
adapter.onBindSuggestion(holder, 0);
adapter.onSuggestionDismissed(suggestions.get(1));
adapter.onSuggestionClosed(suggestions.get(1));
// verify operations that access the lists will not cause ConcurrentModificationException
assertThat(holder.data.getAdapter().getItemCount()).isEqualTo(1);
assertThat(holder.data.getAdapter().getItemCount()).isEqualTo(3);
adapter.setSuggestions(suggestions);
// should not crash
}
@@ -176,42 +159,25 @@ public class DashboardAdapterTest {
@Test
public void testSuggestionDismissed_onlySuggestion_updateDashboardData() {
DashboardAdapter adapter =
spy(new DashboardAdapter(mContext, null, null, null, null));
spy(new DashboardAdapter(mContext, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /*
lifecycle */));
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
adapter.setSuggestions(suggestions);
final DashboardData dashboardData = adapter.mDashboardData;
reset(adapter); // clear interactions tracking
adapter.onSuggestionDismissed(suggestions.get(0));
adapter.onSuggestionClosed(suggestions.get(0));
assertThat(adapter.mDashboardData).isNotEqualTo(dashboardData);
verify(adapter).notifyDashboardDataChanged(any());
}
@Test
public void testSetCategories_iconTinted() {
TypedArray mockTypedArray = mock(TypedArray.class);
doReturn(mockTypedArray).when(mContext).obtainStyledAttributes(any(int[].class));
doReturn(0x89000000).when(mockTypedArray).getColor(anyInt(), anyInt());
final DashboardCategory category = new DashboardCategory();
final Icon mockIcon = mock(Icon.class);
final Tile tile = new Tile();
tile.isIconTintable = true;
tile.icon = mockIcon;
category.addTile(tile);
mDashboardAdapter.setCategory(category);
verify(mockIcon).setTint(eq(0x89000000));
}
@Test
public void testBindConditionAndSuggestion_v2_shouldSetSuggestionAdapterAndNoCrash() {
mDashboardAdapter = new DashboardAdapter(mContext, null, null, null, null);
public void testBindSuggestion_shouldSetSuggestionAdapterAndNoCrash() {
mDashboardAdapter = new DashboardAdapter(mContext, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
final DashboardCategory category = new DashboardCategory();
category.addTile(mock(Tile.class));
mDashboardAdapter.setSuggestions(suggestions);
@@ -220,17 +186,88 @@ public class DashboardAdapterTest {
when(data.getContext()).thenReturn(mContext);
when(mResources.getDisplayMetrics()).thenReturn(mock(DisplayMetrics.class));
final View itemView = mock(View.class);
when(itemView.findViewById(R.id.data)).thenReturn(data);
final DashboardAdapter.SuggestionAndConditionContainerHolder holder =
new DashboardAdapter.SuggestionAndConditionContainerHolder(itemView);
when(itemView.findViewById(R.id.suggestion_list)).thenReturn(data);
when(itemView.findViewById(android.R.id.summary)).thenReturn(mock(TextView.class));
final DashboardAdapter.SuggestionContainerHolder holder =
new DashboardAdapter.SuggestionContainerHolder(itemView);
mDashboardAdapter.onBindConditionAndSuggestion(
holder, DashboardAdapter.SUGGESTION_CONDITION_HEADER_POSITION);
mDashboardAdapter.onBindSuggestion(holder, 0);
verify(data).setAdapter(any(SuggestionAdapter.class));
// should not crash
}
@Test
public void testBindSuggestion_shouldSetSummary() {
mDashboardAdapter = new DashboardAdapter(mContext, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
mDashboardAdapter.setSuggestions(suggestions);
final RecyclerView data = mock(RecyclerView.class);
when(data.getResources()).thenReturn(mResources);
when(data.getContext()).thenReturn(mContext);
when(mResources.getDisplayMetrics()).thenReturn(mock(DisplayMetrics.class));
final View itemView = mock(View.class);
when(itemView.findViewById(R.id.suggestion_list)).thenReturn(data);
final TextView summary = mock(TextView.class);
when(itemView.findViewById(android.R.id.summary)).thenReturn(summary);
final DashboardAdapter.SuggestionContainerHolder holder =
new DashboardAdapter.SuggestionContainerHolder(itemView);
mDashboardAdapter.onBindSuggestion(holder, 0);
verify(summary).setText("1");
suggestions.addAll(makeSuggestionsV2("pkg2", "pkg3", "pkg4"));
mDashboardAdapter.setSuggestions(suggestions);
mDashboardAdapter.onBindSuggestion(holder, 0);
verify(summary).setText("4");
}
@Test
public void onBindTile_internalTile_shouldNotUseGenericBackgroundIcon() {
final Context context = RuntimeEnvironment.application;
final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
final DashboardAdapter.DashboardItemHolder holder =
new DashboardAdapter.DashboardItemHolder(view);
final Tile tile = new Tile();
tile.icon = Icon.createWithResource(context, R.drawable.ic_settings);
final DashboardAdapter.IconCache iconCache = mock(DashboardAdapter.IconCache.class);
when(iconCache.getIcon(tile.icon)).thenReturn(context.getDrawable(R.drawable.ic_settings));
mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);
mDashboardAdapter.onBindTile(holder, tile);
verify(iconCache, never()).updateIcon(any(Icon.class), any(Drawable.class));
}
@Test
public void onBindTile_externalTile_shouldNotUseGenericBackgroundIcon() {
final Context context = RuntimeEnvironment.application;
final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
final DashboardAdapter.DashboardItemHolder holder =
new DashboardAdapter.DashboardItemHolder(view);
final Tile tile = new Tile();
tile.icon = mock(Icon.class);
when(tile.icon.getResPackage()).thenReturn("another.package");
final DashboardAdapter.IconCache iconCache = mock(DashboardAdapter.IconCache.class);
when(iconCache.getIcon(tile.icon)).thenReturn(context.getDrawable(R.drawable.ic_settings));
mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);
mDashboardAdapter.onBindTile(holder, tile);
verify(iconCache).updateIcon(eq(tile.icon), any(RoundedHomepageIcon.class));
}
private List<Suggestion> makeSuggestionsV2(String... pkgNames) {
final List<Suggestion> suggestions = new ArrayList<>();
for (String pkgName : pkgNames) {
@@ -245,8 +282,5 @@ public class DashboardAdapterTest {
private void setupSuggestions(List<Suggestion> suggestions) {
final Context context = RuntimeEnvironment.application;
mDashboardAdapter.setSuggestions(suggestions);
mSuggestionHolder = new DashboardAdapter.SuggestionAndConditionHeaderHolder(
LayoutInflater.from(context).inflate(
R.layout.suggestion_condition_header, new RelativeLayout(context), true));
}
}

View File

@@ -1,286 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.dashboard;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.PendingIntent;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.service.settings.suggestions.Suggestion;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.TestConfig;
import com.android.settings.dashboard.conditional.Condition;
import com.android.settings.dashboard.suggestions.SuggestionAdapterV2;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settingslib.drawer.Tile;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
})
public class DashboardAdapterV2Test {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private SettingsActivity mContext;
@Mock
private View mView;
@Mock
private Condition mCondition;
@Mock
private Resources mResources;
private FakeFeatureFactory mFactory;
private DashboardAdapterV2 mDashboardAdapter;
private List<Condition> mConditionList;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mFactory = FakeFeatureFactory.setupForTest();
when(mFactory.dashboardFeatureProvider.shouldTintIcon()).thenReturn(true);
when(mContext.getResources()).thenReturn(mResources);
when(mResources.getQuantityString(any(int.class), any(int.class), any()))
.thenReturn("");
mConditionList = new ArrayList<>();
mConditionList.add(mCondition);
when(mCondition.shouldShow()).thenReturn(true);
mDashboardAdapter = new DashboardAdapterV2(mContext, null /* savedInstanceState */,
mConditionList, null /* suggestionControllerMixin */, null /* lifecycle */);
when(mView.getTag()).thenReturn(mCondition);
}
@Test
public void testSuggestionDismissed_notOnlySuggestion_updateSuggestionOnly() {
final DashboardAdapterV2 adapter =
spy(new DashboardAdapterV2(mContext, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /*
lifecycle */));
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1", "pkg2", "pkg3");
adapter.setSuggestions(suggestions);
final RecyclerView data = mock(RecyclerView.class);
when(data.getResources()).thenReturn(mResources);
when(data.getContext()).thenReturn(mContext);
when(mResources.getDisplayMetrics()).thenReturn(mock(DisplayMetrics.class));
final View itemView = mock(View.class);
when(itemView.findViewById(R.id.suggestion_list)).thenReturn(data);
when(itemView.findViewById(android.R.id.summary)).thenReturn(mock(TextView.class));
final DashboardAdapterV2.SuggestionContainerHolder holder =
new DashboardAdapterV2.SuggestionContainerHolder(itemView);
adapter.onBindSuggestion(holder, 0);
final DashboardDataV2 dashboardData = adapter.mDashboardData;
reset(adapter); // clear interactions tracking
final Suggestion suggestionToRemove = suggestions.get(1);
adapter.onSuggestionClosed(suggestionToRemove);
assertThat(adapter.mDashboardData).isEqualTo(dashboardData);
assertThat(suggestions.size()).isEqualTo(2);
assertThat(suggestions.contains(suggestionToRemove)).isFalse();
verify(adapter, never()).notifyDashboardDataChanged(any());
}
@Test
public void testSuggestionDismissed_moreThanTwoSuggestions_shouldNotCrash() {
final RecyclerView data = new RecyclerView(RuntimeEnvironment.application);
final View itemView = mock(View.class);
when(itemView.findViewById(R.id.suggestion_list)).thenReturn(data);
when(itemView.findViewById(android.R.id.summary)).thenReturn(mock(TextView.class));
final DashboardAdapterV2.SuggestionContainerHolder holder =
new DashboardAdapterV2.SuggestionContainerHolder(itemView);
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1", "pkg2", "pkg3", "pkg4");
final DashboardAdapterV2 adapter = spy(new DashboardAdapterV2(mContext,
null /*savedInstance */, null /* conditions */,
null /* suggestionControllerMixin */,
null /* lifecycle */));
adapter.setSuggestions(suggestions);
adapter.onBindSuggestion(holder, 0);
adapter.onSuggestionClosed(suggestions.get(1));
// verify operations that access the lists will not cause ConcurrentModificationException
assertThat(holder.data.getAdapter().getItemCount()).isEqualTo(3);
adapter.setSuggestions(suggestions);
// should not crash
}
@Test
public void testSuggestionDismissed_onlySuggestion_updateDashboardData() {
DashboardAdapterV2 adapter =
spy(new DashboardAdapterV2(mContext, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /*
lifecycle */));
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
adapter.setSuggestions(suggestions);
final DashboardDataV2 dashboardData = adapter.mDashboardData;
reset(adapter); // clear interactions tracking
adapter.onSuggestionClosed(suggestions.get(0));
assertThat(adapter.mDashboardData).isNotEqualTo(dashboardData);
verify(adapter).notifyDashboardDataChanged(any());
}
@Test
public void testBindSuggestion_shouldSetSuggestionAdapterAndNoCrash() {
mDashboardAdapter = new DashboardAdapterV2(mContext, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
mDashboardAdapter.setSuggestions(suggestions);
final RecyclerView data = mock(RecyclerView.class);
when(data.getResources()).thenReturn(mResources);
when(data.getContext()).thenReturn(mContext);
when(mResources.getDisplayMetrics()).thenReturn(mock(DisplayMetrics.class));
final View itemView = mock(View.class);
when(itemView.findViewById(R.id.suggestion_list)).thenReturn(data);
when(itemView.findViewById(android.R.id.summary)).thenReturn(mock(TextView.class));
final DashboardAdapterV2.SuggestionContainerHolder holder =
new DashboardAdapterV2.SuggestionContainerHolder(itemView);
mDashboardAdapter.onBindSuggestion(holder, 0);
verify(data).setAdapter(any(SuggestionAdapterV2.class));
// should not crash
}
@Test
public void testBindSuggestion_shouldSetSummary() {
mDashboardAdapter = new DashboardAdapterV2(mContext, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
final List<Suggestion> suggestions = makeSuggestionsV2("pkg1");
mDashboardAdapter.setSuggestions(suggestions);
final RecyclerView data = mock(RecyclerView.class);
when(data.getResources()).thenReturn(mResources);
when(data.getContext()).thenReturn(mContext);
when(mResources.getDisplayMetrics()).thenReturn(mock(DisplayMetrics.class));
final View itemView = mock(View.class);
when(itemView.findViewById(R.id.suggestion_list)).thenReturn(data);
final TextView summary = mock(TextView.class);
when(itemView.findViewById(android.R.id.summary)).thenReturn(summary);
final DashboardAdapterV2.SuggestionContainerHolder holder =
new DashboardAdapterV2.SuggestionContainerHolder(itemView);
mDashboardAdapter.onBindSuggestion(holder, 0);
verify(summary).setText("1");
suggestions.addAll(makeSuggestionsV2("pkg2", "pkg3", "pkg4"));
mDashboardAdapter.setSuggestions(suggestions);
mDashboardAdapter.onBindSuggestion(holder, 0);
verify(summary).setText("4");
}
@Test
public void onBindTile_internalTile_shouldNotUseGenericBackgroundIcon() {
final Context context = RuntimeEnvironment.application;
final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
final DashboardAdapterV2.DashboardItemHolder holder =
new DashboardAdapterV2.DashboardItemHolder(view);
final Tile tile = new Tile();
tile.icon = Icon.createWithResource(context, R.drawable.ic_settings);
final DashboardAdapterV2.IconCache iconCache = mock(DashboardAdapterV2.IconCache.class);
when(iconCache.getIcon(tile.icon)).thenReturn(context.getDrawable(R.drawable.ic_settings));
mDashboardAdapter = new DashboardAdapterV2(context, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);
mDashboardAdapter.onBindTile(holder, tile);
verify(iconCache, never()).updateIcon(any(Icon.class), any(Drawable.class));
}
@Test
public void onBindTile_externalTile_shouldNotUseGenericBackgroundIcon() {
final Context context = RuntimeEnvironment.application;
final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
final DashboardAdapterV2.DashboardItemHolder holder =
new DashboardAdapterV2.DashboardItemHolder(view);
final Tile tile = new Tile();
tile.icon = mock(Icon.class);
when(tile.icon.getResPackage()).thenReturn("another.package");
final DashboardAdapterV2.IconCache iconCache = mock(DashboardAdapterV2.IconCache.class);
when(iconCache.getIcon(tile.icon)).thenReturn(context.getDrawable(R.drawable.ic_settings));
mDashboardAdapter = new DashboardAdapterV2(context, null /* savedInstanceState */,
null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);
mDashboardAdapter.onBindTile(holder, tile);
verify(iconCache).updateIcon(eq(tile.icon), any(RoundedHomepageIcon.class));
}
private List<Suggestion> makeSuggestionsV2(String... pkgNames) {
final List<Suggestion> suggestions = new ArrayList<>();
for (String pkgName : pkgNames) {
final Suggestion suggestion = new Suggestion.Builder(pkgName)
.setPendingIntent(mock(PendingIntent.class))
.build();
suggestions.add(suggestion);
}
return suggestions;
}
private void setupSuggestions(List<Suggestion> suggestions) {
final Context context = RuntimeEnvironment.application;
mDashboardAdapter.setSuggestions(suggestions);
}
}

View File

@@ -17,8 +17,9 @@
package com.android.settings.dashboard;
import static com.android.settings.dashboard.DashboardData.STABLE_ID_CONDITION_CONTAINER;
import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONDITION_FOOTER;
import static com.android.settings.dashboard.DashboardData.STABLE_ID_CONDITION_FOOTER;
import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONTAINER;
import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONDITION_DIVIDER;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -103,14 +104,14 @@ public class DashboardDataTest {
.setConditions(oneItemConditions)
.setCategory(mDashboardCategory)
.setSuggestions(suggestions)
.setSuggestionConditionMode(DashboardData.HEADER_MODE_FULLY_EXPANDED)
.setConditionExpanded(true)
.build();
mDashboardDataWithTwoConditions = new DashboardData.Builder()
.setConditions(twoItemsConditions)
.setCategory(mDashboardCategory)
.setSuggestions(suggestions)
.setSuggestionConditionMode(DashboardData.HEADER_MODE_FULLY_EXPANDED)
.setConditionExpanded(true)
.build();
mDashboardDataWithNoItems = new DashboardData.Builder()
@@ -124,21 +125,23 @@ public class DashboardDataTest {
public void testBuildItemsData_shouldSetstableId() {
final List<DashboardData.Item> items = mDashboardDataWithOneConditions.getItemList();
// Header, suggestion, condition, footer, 1 tile
assertThat(items).hasSize(4);
// suggestion, seperator, condition, footer, 1 tile
assertThat(items).hasSize(5);
assertThat(items.get(0).id).isEqualTo(STABLE_ID_SUGGESTION_CONTAINER);
assertThat(items.get(1).id).isEqualTo(STABLE_ID_CONDITION_CONTAINER);
assertThat(items.get(2).id).isEqualTo(STABLE_ID_SUGGESTION_CONDITION_FOOTER);
assertThat(items.get(3).id).isEqualTo(Objects.hash(mTestCategoryTile.title));
assertThat(items.get(1).id).isEqualTo(STABLE_ID_SUGGESTION_CONDITION_DIVIDER);
assertThat(items.get(2).id).isEqualTo(STABLE_ID_CONDITION_CONTAINER);
assertThat(items.get(3).id).isEqualTo(STABLE_ID_CONDITION_FOOTER);
assertThat(items.get(4).id).isEqualTo(Objects.hash(mTestCategoryTile.title));
}
@Test
public void testBuildItemsData_containsAllData() {
final Object[] expectedObjects = {
mDashboardDataWithOneConditions.getSuggestions(),
null /* divider */,
mDashboardDataWithOneConditions.getConditions(),
null, mTestCategoryTile};
null /* footer */, mTestCategoryTile};
final int expectedSize = expectedObjects.length;
assertThat(mDashboardDataWithOneConditions.getItemList()).hasSize(expectedSize);
@@ -147,14 +150,13 @@ public class DashboardDataTest {
final Object item = mDashboardDataWithOneConditions.getItemEntityByPosition(i);
if (item instanceof List) {
assertThat(item).isEqualTo(expectedObjects[i]);
} else if (item instanceof DashboardData.SuggestionConditionHeaderData) {
DashboardData.SuggestionConditionHeaderData i1 =
(DashboardData.SuggestionConditionHeaderData) item;
DashboardData.SuggestionConditionHeaderData i2 =
(DashboardData.SuggestionConditionHeaderData) expectedObjects[i];
} else if (item instanceof DashboardData.ConditionHeaderData) {
DashboardData.ConditionHeaderData i1 =
(DashboardData.ConditionHeaderData) item;
DashboardData.ConditionHeaderData i2 =
(DashboardData.ConditionHeaderData) expectedObjects[i];
assertThat(i1.title).isEqualTo(i2.title);
assertThat(i1.conditionCount).isEqualTo(i2.conditionCount);
assertThat(i1.hiddenSuggestionCount).isEqualTo(i2.hiddenSuggestionCount);
} else {
assertThat(item).isSameAs(expectedObjects[i]);
}
@@ -209,10 +211,10 @@ public class DashboardDataTest {
public void testDiffUtil_InsertOneCondition_ResultDataOneChanged() {
//Build testResultData
final List<ListUpdateResult.ResultData> testResultData = new ArrayList<>();
// Item in position 2 is the condition container containing the list of conditions, which
// Item in position 3 is the condition container containing the list of conditions, which
// gets 1 more item
testResultData.add(new ListUpdateResult.ResultData(
ListUpdateResult.ResultData.TYPE_OPERATION_CHANGE, 1, 1));
ListUpdateResult.ResultData.TYPE_OPERATION_CHANGE, 2, 1));
testDiffUtil(mDashboardDataWithOneConditions,
mDashboardDataWithTwoConditions, testResultData);
@@ -222,10 +224,11 @@ public class DashboardDataTest {
public void testDiffUtil_RemoveOneSuggestion_causeItemRemoveAndChange() {
//Build testResultData
final List<ListUpdateResult.ResultData> testResultData = new ArrayList<>();
// removed suggestion and the divider
testResultData.add(new ListUpdateResult.ResultData(
ListUpdateResult.ResultData.TYPE_OPERATION_REMOVE, 0, 1));
ListUpdateResult.ResultData.TYPE_OPERATION_REMOVE, 0, 2));
testResultData.add(new ListUpdateResult.ResultData(
ListUpdateResult.ResultData.TYPE_OPERATION_CHANGE, 1, 1));
ListUpdateResult.ResultData.TYPE_OPERATION_CHANGE, 2, 1));
// Build DashboardData
final List<Condition> oneItemConditions = new ArrayList<>();
when(mTestCondition.shouldShow()).thenReturn(true);
@@ -237,13 +240,13 @@ public class DashboardDataTest {
.setConditions(oneItemConditions)
.setCategory(mDashboardCategory)
.setSuggestions(suggestions)
.setSuggestionConditionMode(DashboardData.HEADER_MODE_DEFAULT)
.setConditionExpanded(false)
.build();
final DashboardData newData = new DashboardData.Builder()
.setConditions(oneItemConditions)
.setSuggestions(null)
.setCategory(mDashboardCategory)
.setSuggestionConditionMode(DashboardData.HEADER_MODE_DEFAULT)
.setConditionExpanded(false)
.build();
testDiffUtil(oldData, newData, testResultData);
@@ -254,7 +257,7 @@ public class DashboardDataTest {
//Build testResultData
final List<ListUpdateResult.ResultData> testResultData = new ArrayList<>();
testResultData.add(new ListUpdateResult.ResultData(
ListUpdateResult.ResultData.TYPE_OPERATION_REMOVE, 0, 4));
ListUpdateResult.ResultData.TYPE_OPERATION_REMOVE, 0, 5));
testDiffUtil(mDashboardDataWithOneConditions, mDashboardDataWithNoItems, testResultData);
}

View File

@@ -164,10 +164,4 @@ public class DashboardSummaryTest {
mSummary.onCategoriesChanged();
verify(mSummary).rebuildUI();
}
@Test
public void onSuggestionDismissed_shouldNotRebuildUI() {
mSummary.onSuggestionDismissed(mock(Suggestion.class));
verify(mSummary, never()).rebuildUI();
}
}

View File

@@ -15,6 +15,11 @@
*/
package com.android.settings.dashboard.conditional;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@@ -22,13 +27,9 @@ import android.view.View;
import android.widget.LinearLayout;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.dashboard.DashboardAdapter;
import com.android.settings.dashboard.DashboardData;
import java.util.ArrayList;
import java.util.List;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
@@ -38,9 +39,8 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -70,35 +70,23 @@ public class ConditionAdapterTest {
}
@Test
public void getItemCount_notFullyExpanded_shouldReturn0() {
mConditionAdapter = new ConditionAdapter(
mContext, mOneCondition, DashboardData.HEADER_MODE_DEFAULT);
assertThat(mConditionAdapter.getItemCount()).isEqualTo(0);
mConditionAdapter = new ConditionAdapter(
mContext, mOneCondition, DashboardData.HEADER_MODE_SUGGESTION_EXPANDED);
assertThat(mConditionAdapter.getItemCount()).isEqualTo(0);
mConditionAdapter = new ConditionAdapter(
mContext, mOneCondition, DashboardData.HEADER_MODE_COLLAPSED);
public void getItemCount_notExpanded_shouldReturn0() {
mConditionAdapter = new ConditionAdapter(mContext, mOneCondition, false);
assertThat(mConditionAdapter.getItemCount()).isEqualTo(0);
}
@Test
public void getItemCount_fullyExpanded_shouldReturnListSize() {
mConditionAdapter = new ConditionAdapter(
mContext, mOneCondition, DashboardData.HEADER_MODE_FULLY_EXPANDED);
public void getItemCount_expanded_shouldReturnListSize() {
mConditionAdapter = new ConditionAdapter(mContext, mOneCondition, true);
assertThat(mConditionAdapter.getItemCount()).isEqualTo(1);
mConditionAdapter = new ConditionAdapter(
mContext, mTwoConditions, DashboardData.HEADER_MODE_FULLY_EXPANDED);
mConditionAdapter = new ConditionAdapter(mContext, mTwoConditions, true);
assertThat(mConditionAdapter.getItemCount()).isEqualTo(2);
}
@Test
public void getItemViewType_shouldReturnConditionTile() {
mConditionAdapter = new ConditionAdapter(
mContext, mTwoConditions, DashboardData.HEADER_MODE_FULLY_EXPANDED);
mConditionAdapter = new ConditionAdapter(mContext, mTwoConditions, true);
assertThat(mConditionAdapter.getItemViewType(0)).isEqualTo(R.layout.condition_tile);
}
@@ -108,8 +96,7 @@ public class ConditionAdapterTest {
R.layout.condition_tile, new LinearLayout(mContext), true);
final DashboardAdapter.DashboardItemHolder viewHolder =
new DashboardAdapter.DashboardItemHolder(view);
mConditionAdapter = new ConditionAdapter(
mContext, mOneCondition, DashboardData.HEADER_MODE_SUGGESTION_EXPANDED);
mConditionAdapter = new ConditionAdapter(mContext, mOneCondition, true);
mConditionAdapter.onBindViewHolder(viewHolder, 0);
final View card = view.findViewById(R.id.content);
@@ -122,8 +109,7 @@ public class ConditionAdapterTest {
R.layout.condition_tile, new LinearLayout(mContext), true);
final DashboardAdapter.DashboardItemHolder viewHolder =
new DashboardAdapter.DashboardItemHolder(view);
mConditionAdapter = new ConditionAdapter(
mContext, mOneCondition, DashboardData.HEADER_MODE_SUGGESTION_EXPANDED);
mConditionAdapter = new ConditionAdapter(mContext, mOneCondition, true);
mConditionAdapter.onBindViewHolder(viewHolder, 0);
final View card = view.findViewById(R.id.content);
@@ -137,9 +123,8 @@ public class ConditionAdapterTest {
final View view = LayoutInflater.from(mContext).inflate(
R.layout.condition_tile, new LinearLayout(mContext), true);
final DashboardAdapter.DashboardItemHolder viewHolder =
new DashboardAdapter.DashboardItemHolder(view);
mConditionAdapter = new ConditionAdapter(
mContext, mOneCondition, DashboardData.HEADER_MODE_SUGGESTION_EXPANDED);
new DashboardAdapter.DashboardItemHolder(view);
mConditionAdapter = new ConditionAdapter(mContext, mOneCondition, true);
mConditionAdapter.addDismissHandling(recyclerView);
// do not bind viewholder to simulate the null condition scenario

View File

@@ -1,135 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.dashboard.conditional;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.dashboard.DashboardAdapterV2;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ConditionAdapterV2Test {
@Mock
private Condition mCondition1;
@Mock
private Condition mCondition2;
private Context mContext;
private ConditionAdapterV2 mConditionAdapter;
private List<Condition> mOneCondition;
private List<Condition> mTwoConditions;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
final CharSequence[] actions = new CharSequence[2];
when(mCondition1.getActions()).thenReturn(actions);
when(mCondition1.shouldShow()).thenReturn(true);
mOneCondition = new ArrayList<>();
mOneCondition.add(mCondition1);
mTwoConditions = new ArrayList<>();
mTwoConditions.add(mCondition1);
mTwoConditions.add(mCondition2);
}
@Test
public void getItemCount_notExpanded_shouldReturn0() {
mConditionAdapter = new ConditionAdapterV2(mContext, mOneCondition, false);
assertThat(mConditionAdapter.getItemCount()).isEqualTo(0);
}
@Test
public void getItemCount_expanded_shouldReturnListSize() {
mConditionAdapter = new ConditionAdapterV2(mContext, mOneCondition, true);
assertThat(mConditionAdapter.getItemCount()).isEqualTo(1);
mConditionAdapter = new ConditionAdapterV2(mContext, mTwoConditions, true);
assertThat(mConditionAdapter.getItemCount()).isEqualTo(2);
}
@Test
public void getItemViewType_shouldReturnConditionTile() {
mConditionAdapter = new ConditionAdapterV2(mContext, mTwoConditions, true);
assertThat(mConditionAdapter.getItemViewType(0)).isEqualTo(R.layout.condition_tile);
}
@Test
public void onBindViewHolder_shouldSetListener() {
final View view = LayoutInflater.from(mContext).inflate(
R.layout.condition_tile, new LinearLayout(mContext), true);
final DashboardAdapterV2.DashboardItemHolder viewHolder =
new DashboardAdapterV2.DashboardItemHolder(view);
mConditionAdapter = new ConditionAdapterV2(mContext, mOneCondition, true);
mConditionAdapter.onBindViewHolder(viewHolder, 0);
final View card = view.findViewById(R.id.content);
assertThat(card.hasOnClickListeners()).isTrue();
}
@Test
public void viewClick_shouldInvokeConditionPrimaryClick() {
final View view = LayoutInflater.from(mContext).inflate(
R.layout.condition_tile, new LinearLayout(mContext), true);
final DashboardAdapterV2.DashboardItemHolder viewHolder =
new DashboardAdapterV2.DashboardItemHolder(view);
mConditionAdapter = new ConditionAdapterV2(mContext, mOneCondition, true);
mConditionAdapter.onBindViewHolder(viewHolder, 0);
final View card = view.findViewById(R.id.content);
card.performClick();
verify(mCondition1).onPrimaryClick();
}
@Test
public void onSwiped_nullCondition_shouldNotCrash() {
final RecyclerView recyclerView = new RecyclerView(mContext);
final View view = LayoutInflater.from(mContext).inflate(
R.layout.condition_tile, new LinearLayout(mContext), true);
final DashboardAdapterV2.DashboardItemHolder viewHolder =
new DashboardAdapterV2.DashboardItemHolder(view);
mConditionAdapter = new ConditionAdapterV2(mContext, mOneCondition, true);
mConditionAdapter.addDismissHandling(recyclerView);
// do not bind viewholder to simulate the null condition scenario
mConditionAdapter.mSwipeCallback.onSwiped(viewHolder, 0);
// no crash
}
}

View File

@@ -16,12 +16,19 @@
package com.android.settings.dashboard.suggestions;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.PendingIntent;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.service.settings.suggestions.Suggestion;
import android.view.LayoutInflater;
@@ -46,6 +53,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@@ -87,20 +95,21 @@ public class SuggestionAdapterTest {
@Test
public void getItemCount_shouldReturnListSize() {
mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin,
mOneSuggestion, new ArrayList<>());
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(mOneSuggestion);
assertThat(mSuggestionAdapter.getItemCount()).isEqualTo(1);
mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin,
mTwoSuggestions, new ArrayList<>());
mSuggestionAdapter.setSuggestions(mTwoSuggestions);
assertThat(mSuggestionAdapter.getItemCount()).isEqualTo(2);
}
@Test
public void getItemViewType_shouldReturnSuggestionTile() {
mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin,
mOneSuggestion, new ArrayList<>());
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(mOneSuggestion);
assertThat(mSuggestionAdapter.getItemViewType(0))
.isEqualTo(R.layout.suggestion_tile);
.isEqualTo(R.layout.suggestion_tile);
}
@Test
@@ -112,19 +121,21 @@ public class SuggestionAdapterTest {
.setSummary("456")
.build());
mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin,
suggestions, new ArrayList<>());
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
assertThat(mSuggestionAdapter.getItemViewType(0))
.isEqualTo(R.layout.suggestion_tile_with_button);
.isEqualTo(R.layout.suggestion_tile_with_button);
}
@Test
public void onBindViewHolder_shouldLog() {
final View view = spy(LayoutInflater.from(mContext).inflate(
R.layout.suggestion_tile, new LinearLayout(mContext), true));
R.layout.suggestion_tile, new LinearLayout(mContext), true));
mSuggestionHolder = new DashboardAdapter.DashboardItemHolder(view);
mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin,
mOneSuggestion, new ArrayList<>());
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(mOneSuggestion);
// Bind twice
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
@@ -149,6 +160,31 @@ public class SuggestionAdapterTest {
verify(suggestions.get(0).getPendingIntent()).send();
}
@Test
public void onBindViewHolder_hasButton_buttonShouldHandleClick()
throws PendingIntent.CanceledException {
final List<Suggestion> suggestions = new ArrayList<>();
final PendingIntent pendingIntent = mock(PendingIntent.class);
suggestions.add(new Suggestion.Builder("id")
.setFlags(Suggestion.FLAG_HAS_BUTTON)
.setTitle("123")
.setSummary("456")
.setPendingIntent(pendingIntent)
.build());
mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
mSuggestionHolder.itemView.findViewById(android.R.id.primary).performClick();
verify(mSuggestionControllerMixin).launchSuggestion(suggestions.get(0));
verify(pendingIntent).send();
}
@Test
public void getSuggestions_shouldReturnSuggestionWhenMatch() {
final List<Suggestion> suggestions = makeSuggestions("pkg1");
@@ -157,9 +193,92 @@ public class SuggestionAdapterTest {
assertThat(mSuggestionAdapter.getSuggestion(0)).isNotNull();
}
@Test
public void onBindViewHolder_closeButtonShouldHandleClick()
throws PendingIntent.CanceledException {
final List<Suggestion> suggestions = makeSuggestions("pkg1");
final SuggestionAdapter.Callback callback = mock(SuggestionAdapter.Callback.class);
mSuggestionAdapter = new SuggestionAdapter(mActivity, mSuggestionControllerMixin,
null /* savedInstanceState */, callback, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
mSuggestionHolder.itemView.findViewById(R.id.close_button).performClick();
final Suggestion suggestion = suggestions.get(0);
verify(mFeatureFactory.suggestionsFeatureProvider).dismissSuggestion(
mActivity, mSuggestionControllerMixin, suggestion);
verify(callback).onSuggestionClosed(suggestion);
}
@Test
public void onBindViewHolder_differentPackage_shouldNotTintIcon()
throws PendingIntent.CanceledException {
final Icon icon = mock(Icon.class);
when(icon.getResPackage()).thenReturn("pkg1");
when(mActivity.getPackageName()).thenReturn("pkg2");
final Suggestion suggestion = new Suggestion.Builder("pkg1")
.setPendingIntent(mock(PendingIntent.class))
.setIcon(icon)
.build();
final List<Suggestion> suggestions = new ArrayList<>();
suggestions.add(suggestion);
mSuggestionAdapter = new SuggestionAdapter(mActivity, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
DashboardAdapter.IconCache cache = mock(DashboardAdapter.IconCache.class);
final Drawable drawable = mock(Drawable.class);
when(cache.getIcon(icon)).thenReturn(drawable);
ReflectionHelpers.setField(mSuggestionAdapter, "mCache", cache);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
verify(drawable, never()).setTint(anyInt());
}
@Test
public void onBindViewHolder_samePackage_shouldTintIcon()
throws PendingIntent.CanceledException {
final Icon icon = mock(Icon.class);
final String packageName = "pkg1";
when(icon.getResPackage()).thenReturn(packageName);
when(mActivity.getPackageName()).thenReturn(packageName);
final Suggestion suggestion = new Suggestion.Builder(packageName)
.setPendingIntent(mock(PendingIntent.class))
.setIcon(icon)
.build();
final List<Suggestion> suggestions = new ArrayList<>();
suggestions.add(suggestion);
mSuggestionAdapter = new SuggestionAdapter(mActivity, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
DashboardAdapter.IconCache cache = mock(DashboardAdapter.IconCache.class);
final Drawable drawable = mock(Drawable.class);
when(cache.getIcon(icon)).thenReturn(drawable);
ReflectionHelpers.setField(mSuggestionAdapter, "mCache", cache);
TypedArray typedArray = mock(TypedArray.class);
final int colorAccent = 1234;
when(mActivity.obtainStyledAttributes(any())).thenReturn(typedArray);
when(typedArray.getColor(anyInt(), anyInt())).thenReturn(colorAccent);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
verify(drawable).setTint(colorAccent);
}
private void setupSuggestions(Context context, List<Suggestion> suggestions) {
mSuggestionAdapter = new SuggestionAdapter(context, mSuggestionControllerMixin,
suggestions, new ArrayList<>());
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));

View File

@@ -1,297 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.dashboard.suggestions;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.PendingIntent;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.service.settings.suggestions.Suggestion;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.TestConfig;
import com.android.settings.dashboard.DashboardAdapterV2;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class SuggestionAdapterV2Test {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private SettingsActivity mActivity;
@Mock
private SuggestionControllerMixin mSuggestionControllerMixin;
private FakeFeatureFactory mFeatureFactory;
private Context mContext;
private SuggestionAdapterV2 mSuggestionAdapter;
private DashboardAdapterV2.DashboardItemHolder mSuggestionHolder;
private List<Suggestion> mOneSuggestion;
private List<Suggestion> mTwoSuggestions;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mFeatureFactory = FakeFeatureFactory.setupForTest();
final Suggestion suggestion1 = new Suggestion.Builder("id1")
.setTitle("Test suggestion 1")
.build();
final Suggestion suggestion2 = new Suggestion.Builder("id2")
.setTitle("Test suggestion 2")
.build();
mOneSuggestion = new ArrayList<>();
mOneSuggestion.add(suggestion1);
mTwoSuggestions = new ArrayList<>();
mTwoSuggestions.add(suggestion1);
mTwoSuggestions.add(suggestion2);
}
@Test
public void getItemCount_shouldReturnListSize() {
mSuggestionAdapter = new SuggestionAdapterV2(mContext, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(mOneSuggestion);
assertThat(mSuggestionAdapter.getItemCount()).isEqualTo(1);
mSuggestionAdapter.setSuggestions(mTwoSuggestions);
assertThat(mSuggestionAdapter.getItemCount()).isEqualTo(2);
}
@Test
public void getItemViewType_shouldReturnSuggestionTile() {
mSuggestionAdapter = new SuggestionAdapterV2(mContext, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(mOneSuggestion);
assertThat(mSuggestionAdapter.getItemViewType(0))
.isEqualTo(R.layout.suggestion_tile_v2);
}
@Test
public void getItemType_hasButton_shouldReturnSuggestionWithButton() {
final List<Suggestion> suggestions = new ArrayList<>();
suggestions.add(new Suggestion.Builder("id")
.setFlags(Suggestion.FLAG_HAS_BUTTON)
.setTitle("123")
.setSummary("456")
.build());
mSuggestionAdapter = new SuggestionAdapterV2(mContext, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
assertThat(mSuggestionAdapter.getItemViewType(0))
.isEqualTo(R.layout.suggestion_tile_with_button_v2);
}
@Test
public void onBindViewHolder_shouldLog() {
final View view = spy(LayoutInflater.from(mContext).inflate(
R.layout.suggestion_tile, new LinearLayout(mContext), true));
mSuggestionHolder = new DashboardAdapterV2.DashboardItemHolder(view);
mSuggestionAdapter = new SuggestionAdapterV2(mContext, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(mOneSuggestion);
// Bind twice
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
// Log once
verify(mFeatureFactory.metricsFeatureProvider).action(
mContext, MetricsProto.MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION,
mOneSuggestion.get(0).getId());
}
@Test
public void onBindViewHolder_itemViewShouldHandleClick()
throws PendingIntent.CanceledException {
final List<Suggestion> suggestions = makeSuggestions("pkg1");
setupSuggestions(mActivity, suggestions);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
mSuggestionHolder.itemView.performClick();
verify(mSuggestionControllerMixin).launchSuggestion(suggestions.get(0));
verify(suggestions.get(0).getPendingIntent()).send();
}
@Test
public void onBindViewHolder_hasButton_buttonShouldHandleClick()
throws PendingIntent.CanceledException {
final List<Suggestion> suggestions = new ArrayList<>();
final PendingIntent pendingIntent = mock(PendingIntent.class);
suggestions.add(new Suggestion.Builder("id")
.setFlags(Suggestion.FLAG_HAS_BUTTON)
.setTitle("123")
.setSummary("456")
.setPendingIntent(pendingIntent)
.build());
mSuggestionAdapter = new SuggestionAdapterV2(mContext, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
mSuggestionHolder.itemView.findViewById(android.R.id.primary).performClick();
verify(mSuggestionControllerMixin).launchSuggestion(suggestions.get(0));
verify(pendingIntent).send();
}
@Test
public void getSuggestions_shouldReturnSuggestionWhenMatch() {
final List<Suggestion> suggestions = makeSuggestions("pkg1");
setupSuggestions(mActivity, suggestions);
assertThat(mSuggestionAdapter.getSuggestion(0)).isNotNull();
}
@Test
public void onBindViewHolder_closeButtonShouldHandleClick()
throws PendingIntent.CanceledException {
final List<Suggestion> suggestions = makeSuggestions("pkg1");
final SuggestionAdapterV2.Callback callback = mock(SuggestionAdapterV2.Callback.class);
mSuggestionAdapter = new SuggestionAdapterV2(mActivity, mSuggestionControllerMixin,
null /* savedInstanceState */, callback, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
mSuggestionHolder.itemView.findViewById(R.id.close_button).performClick();
final Suggestion suggestion = suggestions.get(0);
verify(mFeatureFactory.suggestionsFeatureProvider).dismissSuggestion(
mActivity, mSuggestionControllerMixin, suggestion);
verify(callback).onSuggestionClosed(suggestion);
}
@Test
public void onBindViewHolder_differentPackage_shouldNotTintIcon()
throws PendingIntent.CanceledException {
final Icon icon = mock(Icon.class);
when(icon.getResPackage()).thenReturn("pkg1");
when(mActivity.getPackageName()).thenReturn("pkg2");
final Suggestion suggestion = new Suggestion.Builder("pkg1")
.setPendingIntent(mock(PendingIntent.class))
.setIcon(icon)
.build();
final List<Suggestion> suggestions = new ArrayList<>();
suggestions.add(suggestion);
mSuggestionAdapter = new SuggestionAdapterV2(mActivity, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
DashboardAdapterV2.IconCache cache = mock(DashboardAdapterV2.IconCache.class);
final Drawable drawable = mock(Drawable.class);
when(cache.getIcon(icon)).thenReturn(drawable);
ReflectionHelpers.setField(mSuggestionAdapter, "mCache", cache);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
verify(drawable, never()).setTint(anyInt());
}
@Test
public void onBindViewHolder_samePackage_shouldTintIcon()
throws PendingIntent.CanceledException {
final Icon icon = mock(Icon.class);
final String packageName = "pkg1";
when(icon.getResPackage()).thenReturn(packageName);
when(mActivity.getPackageName()).thenReturn(packageName);
final Suggestion suggestion = new Suggestion.Builder(packageName)
.setPendingIntent(mock(PendingIntent.class))
.setIcon(icon)
.build();
final List<Suggestion> suggestions = new ArrayList<>();
suggestions.add(suggestion);
mSuggestionAdapter = new SuggestionAdapterV2(mActivity, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
DashboardAdapterV2.IconCache cache = mock(DashboardAdapterV2.IconCache.class);
final Drawable drawable = mock(Drawable.class);
when(cache.getIcon(icon)).thenReturn(drawable);
ReflectionHelpers.setField(mSuggestionAdapter, "mCache", cache);
TypedArray typedArray = mock(TypedArray.class);
final int colorAccent = 1234;
when(mActivity.obtainStyledAttributes(any())).thenReturn(typedArray);
when(typedArray.getColor(anyInt(), anyInt())).thenReturn(colorAccent);
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
verify(drawable).setTint(colorAccent);
}
private void setupSuggestions(Context context, List<Suggestion> suggestions) {
mSuggestionAdapter = new SuggestionAdapterV2(context, mSuggestionControllerMixin,
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
mSuggestionAdapter.setSuggestions(suggestions);
mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
new FrameLayout(RuntimeEnvironment.application),
mSuggestionAdapter.getItemViewType(0));
}
private List<Suggestion> makeSuggestions(String... pkgNames) {
final List<Suggestion> suggestions = new ArrayList<>();
for (String pkgName : pkgNames) {
final Suggestion suggestion = new Suggestion.Builder(pkgName)
.setPendingIntent(mock(PendingIntent.class))
.build();
suggestions.add(suggestion);
}
return suggestions;
}
}

View File

@@ -1,117 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.dashboard.suggestions;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.service.settings.suggestions.Suggestion;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class SuggestionDismissControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private RecyclerView mRecyclerView;
@Mock
private SuggestionControllerMixin mSuggestionControllerMixin;
@Mock
private SuggestionDismissController.Callback mCallback;
private FakeFeatureFactory mFactory;
private SuggestionDismissController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mFactory = FakeFeatureFactory.setupForTest();
when(mRecyclerView.getResources().getDimension(anyInt())).thenReturn(50F);
mController = new SuggestionDismissController(mContext, mRecyclerView,
mSuggestionControllerMixin, mCallback);
}
@Test
public void onMove_alwaysReturnTrue() {
assertThat(mController.onMove(null, null, null)).isTrue();
}
@Test
public void getSwipeDirs_isSuggestionTile_shouldReturnDirection() {
final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
when(vh.getItemViewType()).thenReturn(R.layout.suggestion_tile);
assertThat(mController.getSwipeDirs(mRecyclerView, vh))
.isEqualTo(ItemTouchHelper.START | ItemTouchHelper.END);
}
@Test
public void getSwipeDirs_isSuggestionTileCard_shouldReturnDirection() {
final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
when(vh.getItemViewType()).thenReturn(R.layout.suggestion_tile_with_button);
assertThat(mController.getSwipeDirs(mRecyclerView, vh))
.isEqualTo(ItemTouchHelper.START | ItemTouchHelper.END);
}
@Test
public void getSwipeDirs_isNotSuggestionTile_shouldReturn0() {
final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
when(vh.getItemViewType()).thenReturn(R.layout.condition_tile);
assertThat(mController.getSwipeDirs(mRecyclerView, vh))
.isEqualTo(0);
}
@Test
public void onSwiped_shouldTriggerDismissSuggestion() {
final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
when(mCallback.getSuggestionAt(anyInt())).thenReturn(
new Suggestion.Builder("id").build());
mController.onSwiped(vh, ItemTouchHelper.START);
verify(mFactory.suggestionsFeatureProvider).dismissSuggestion(
eq(mContext), eq(mSuggestionControllerMixin), nullable(Suggestion.class));
verify(mCallback).onSuggestionDismissed(nullable(Suggestion.class));
}
}