From 307d2093224bcc78b441c0589b3d3e16ca2a6f55 Mon Sep 17 00:00:00 2001 From: Emily Chuang Date: Wed, 29 Aug 2018 19:47:00 +0800 Subject: [PATCH] Add conditional cards to the new homepage. Make existing Settings Conditions show up in the new homepage as custom view. Bug: 113451905 Test: robotests Change-Id: Ic49089f95ff04442a887cda97481e945136f7209 --- res/layout/homepage_condition_tile.xml | 29 ++++ res/values/dimens.xml | 3 + .../homepage/ControllerRendererPool.java | 12 +- .../settings/homepage/HomepageCard.java | 40 ++--- .../homepage/HomepageCardController.java | 2 - .../homepage/HomepageCardLookupTable.java | 10 +- .../homepage/HomepageCardUpdateListener.java | 2 +- .../homepage/conditional/ConditionCard.java | 78 ++++++++++ .../ConditionHomepageCardController.java | 111 ++++++++++++++ .../ConditionHomepageCardRenderer.java | 137 +++++++++++++++++ .../ConditionHomepageCardControllerTest.java | 138 ++++++++++++++++++ .../ConditionHomepageCardRendererTest.java | 112 ++++++++++++++ 12 files changed, 641 insertions(+), 33 deletions(-) create mode 100644 res/layout/homepage_condition_tile.xml create mode 100644 src/com/android/settings/homepage/conditional/ConditionCard.java create mode 100644 src/com/android/settings/homepage/conditional/ConditionHomepageCardController.java create mode 100644 src/com/android/settings/homepage/conditional/ConditionHomepageCardRenderer.java create mode 100644 tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardRendererTest.java diff --git a/res/layout/homepage_condition_tile.xml b/res/layout/homepage_condition_tile.xml new file mode 100644 index 00000000000..50ef3c250d2 --- /dev/null +++ b/res/layout/homepage_condition_tile.xml @@ -0,0 +1,29 @@ + + + + + + + diff --git a/res/values/dimens.xml b/res/values/dimens.xml index acb895ba7b6..be57bf77527 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -312,6 +312,9 @@ 16dp 18dp + + 2dp + 8dp 12dp diff --git a/src/com/android/settings/homepage/ControllerRendererPool.java b/src/com/android/settings/homepage/ControllerRendererPool.java index b2ac9ecde9f..ebd63d4ff9b 100644 --- a/src/com/android/settings/homepage/ControllerRendererPool.java +++ b/src/com/android/settings/homepage/ControllerRendererPool.java @@ -21,6 +21,9 @@ import android.util.Log; import androidx.collection.ArraySet; +import com.android.settings.homepage.conditional.ConditionHomepageCardController; +import com.android.settings.homepage.conditional.ConditionHomepageCardRenderer; + import java.util.Set; /** @@ -80,19 +83,16 @@ public class ControllerRendererPool { private HomepageCardController createCardController(Context context, Class clz) { - /* if (ConditionHomepageCardController.class == clz) { return new ConditionHomepageCardController(context); } - */ return null; } private HomepageCardRenderer createCardRenderer(Context context, Class clz) { - //if (ConditionHomepageCardRenderer.class == clz) { - // return new ConditionHomepageCardRenderer(context, this /*controllerRendererPool*/); - //} - + if (ConditionHomepageCardRenderer.class == clz) { + return new ConditionHomepageCardRenderer(context, this /*controllerRendererPool*/); + } return null; } diff --git a/src/com/android/settings/homepage/HomepageCard.java b/src/com/android/settings/homepage/HomepageCard.java index 588c7588cd5..1469ff1896d 100644 --- a/src/com/android/settings/homepage/HomepageCard.java +++ b/src/com/android/settings/homepage/HomepageCard.java @@ -65,79 +65,79 @@ public class HomepageCard { return mName; } - int getCardType() { + public int getCardType() { return mCardType; } - double getRankingScore() { + public double getRankingScore() { return mRankingScore; } - String getTextSliceUri() { + public String getTextSliceUri() { return mSliceUri; } - Uri getSliceUri() { + public Uri getSliceUri() { return Uri.parse(mSliceUri); } - int getCategory() { + public int getCategory() { return mCategory; } - String getLocalizedToLocale() { + public String getLocalizedToLocale() { return mLocalizedToLocale; } - String getPackageName() { + public String getPackageName() { return mPackageName; } - String getAppVersion() { + public String getAppVersion() { return mAppVersion; } - String getTitleResName() { + public String getTitleResName() { return mTitleResName; } - String getTitleText() { + public String getTitleText() { return mTitleText; } - String getSummaryResName() { + public String getSummaryResName() { return mSummaryResName; } - String getSummaryText() { + public String getSummaryText() { return mSummaryText; } - String getIconResName() { + public String getIconResName() { return mIconResName; } - int getIconResId() { + public int getIconResId() { return mIconResId; } - int getCardAction() { + public int getCardAction() { return mCardAction; } - long getExpireTimeMS() { + public long getExpireTimeMS() { return mExpireTimeMS; } - Drawable getIconDrawable() { + public Drawable getIconDrawable() { return mIconDrawable; } - boolean isHalfWidth() { + public boolean isHalfWidth() { return mIsHalfWidth; } - HomepageCard(Builder builder) { + public HomepageCard(Builder builder) { mName = builder.mName; mCardType = builder.mCardType; mRankingScore = builder.mRankingScore; @@ -179,7 +179,7 @@ public class HomepageCard { return TextUtils.equals(mName, that.mName); } - static class Builder { + public static class Builder { private String mName; private int mCardType; private double mRankingScore; diff --git a/src/com/android/settings/homepage/HomepageCardController.java b/src/com/android/settings/homepage/HomepageCardController.java index 10fc158f688..a7d89afc504 100644 --- a/src/com/android/settings/homepage/HomepageCardController.java +++ b/src/com/android/settings/homepage/HomepageCardController.java @@ -18,8 +18,6 @@ package com.android.settings.homepage; import java.util.List; -//TODO(b/111821137): add test cases - /** * Data controller for {@link HomepageCard}. */ diff --git a/src/com/android/settings/homepage/HomepageCardLookupTable.java b/src/com/android/settings/homepage/HomepageCardLookupTable.java index ae3f08b467f..8d8e52b183e 100644 --- a/src/com/android/settings/homepage/HomepageCardLookupTable.java +++ b/src/com/android/settings/homepage/HomepageCardLookupTable.java @@ -17,6 +17,8 @@ package com.android.settings.homepage; import com.android.settings.homepage.HomepageCard.CardType; +import com.android.settings.homepage.conditional.ConditionHomepageCardController; +import com.android.settings.homepage.conditional.ConditionHomepageCardRenderer; import java.util.Set; import java.util.TreeSet; @@ -43,10 +45,10 @@ public class HomepageCardLookupTable { } } - private static final Set LOOKUP_TABLE = new TreeSet() { - //add(new HomepageMapping(CardType.CONDITIONAL, ConditionHomepageCardController.class, - // ConditionHomepageCardRenderer.class)); - }; + private static final Set LOOKUP_TABLE = new TreeSet() {{ + add(new HomepageMapping(CardType.CONDITIONAL, ConditionHomepageCardController.class, + ConditionHomepageCardRenderer.class)); + }}; public static Class getCardControllerClass( @CardType int cardType) { diff --git a/src/com/android/settings/homepage/HomepageCardUpdateListener.java b/src/com/android/settings/homepage/HomepageCardUpdateListener.java index a44ba2be6e3..35bc3a34bf1 100644 --- a/src/com/android/settings/homepage/HomepageCardUpdateListener.java +++ b/src/com/android/settings/homepage/HomepageCardUpdateListener.java @@ -26,6 +26,6 @@ import java.util.List; * {@link HomepageManager} will notify the listeners registered, {@link HomepageAdapter} in this * case. */ -interface HomepageCardUpdateListener { +public interface HomepageCardUpdateListener { void onHomepageCardUpdated(int cardType, List updateList); } \ No newline at end of file diff --git a/src/com/android/settings/homepage/conditional/ConditionCard.java b/src/com/android/settings/homepage/conditional/ConditionCard.java new file mode 100644 index 00000000000..9f445b2afd6 --- /dev/null +++ b/src/com/android/settings/homepage/conditional/ConditionCard.java @@ -0,0 +1,78 @@ +/* + * 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.homepage.conditional; + +import com.android.settings.homepage.HomepageCard; + +/** + * Data class representing a {@link ConditionCard}. + * + * Use this class to store additional attributes on top of {@link HomepageCard} for + * {@link ConditionalCard}. + */ +public class ConditionCard extends HomepageCard { + + private final long mConditionId; + private final int mMetricsConstant; + private final CharSequence mActionText; + + private ConditionCard(Builder builder) { + super(builder); + + mConditionId = builder.mConditionId; + mMetricsConstant = builder.mMetricsConstant; + mActionText = builder.mActionText; + } + + public long getConditionId() { + return mConditionId; + } + + public int getMetricsConstant() { + return mMetricsConstant; + } + + public CharSequence getActionText() { + return mActionText; + } + + static class Builder extends HomepageCard.Builder { + + private long mConditionId; + private int mMetricsConstant; + private CharSequence mActionText; + + public Builder setConditionId(long id) { + mConditionId = id; + return this; + } + + public Builder setMetricsConstant(int metricsConstant) { + mMetricsConstant = metricsConstant; + return this; + } + + public Builder setActionText(CharSequence actionText) { + mActionText = actionText; + return this; + } + + public ConditionCard build() { + return new ConditionCard(this); + } + } +} \ No newline at end of file diff --git a/src/com/android/settings/homepage/conditional/ConditionHomepageCardController.java b/src/com/android/settings/homepage/conditional/ConditionHomepageCardController.java new file mode 100644 index 00000000000..bb7af4b7084 --- /dev/null +++ b/src/com/android/settings/homepage/conditional/ConditionHomepageCardController.java @@ -0,0 +1,111 @@ +/* + * 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.homepage.conditional; + +import android.content.Context; + +import com.android.settings.homepage.HomepageCard; +import com.android.settings.homepage.HomepageCardController; +import com.android.settings.homepage.HomepageCardUpdateListener; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +import java.util.ArrayList; +import java.util.List; + +/** + * This controller triggers the loading of conditional cards and monitors state changes to + * update the homepage. + */ +public class ConditionHomepageCardController implements HomepageCardController, ConditionListener, + LifecycleObserver, OnStart, OnStop { + + private final Context mContext; + private final ConditionManager mConditionManager; + + private HomepageCardUpdateListener mListener; + + public ConditionHomepageCardController(Context context) { + mContext = context; + mConditionManager = new ConditionManager(context.getApplicationContext(), this); + mConditionManager.startMonitoringStateChange(); + } + + @Override + public void setHomepageCardUpdateListener(HomepageCardUpdateListener listener) { + mListener = listener; + } + + @Override + public int getCardType() { + return HomepageCard.CardType.CONDITIONAL; + } + + @Override + public void onDataUpdated(List cardList) { + mListener.onHomepageCardUpdated(getCardType(), cardList); + } + + @Override + public void onStart() { + mConditionManager.startMonitoringStateChange(); + } + + @Override + public void onStop() { + mConditionManager.stopMonitoringStateChange(); + } + + @Override + public void onPrimaryClick(HomepageCard homepageCard) { + final ConditionCard card = (ConditionCard) homepageCard; + mConditionManager.onPrimaryClick(mContext, card.getConditionId()); + + } + + @Override + public void onActionClick(HomepageCard homepageCard) { + final ConditionCard card = (ConditionCard) homepageCard; + mConditionManager.onActionClick(card.getConditionId()); + } + + @Override + public void onConditionsChanged() { + final List conditionCards = new ArrayList<>(); + final List conditionList = mConditionManager.getDisplayableCards(); + + for (ConditionalCard condition : conditionList) { + final ConditionCard conditionCard = ((ConditionCard.Builder) new ConditionCard.Builder() + .setConditionId(condition.getId()) + .setMetricsConstant(condition.getMetricsConstant()) + .setActionText(condition.getActionText()) + .setName(mContext.getPackageName() + "/" + condition.getTitle().toString()) + .setCardType(HomepageCard.CardType.CONDITIONAL) + .setTitleText(condition.getTitle().toString()) + .setSummaryText(condition.getSummary().toString()) + .setIconDrawable(condition.getIcon())) + .build(); + + conditionCards.add(conditionCard); + } + + if (mListener != null) { + onDataUpdated(conditionCards); + } + } +} diff --git a/src/com/android/settings/homepage/conditional/ConditionHomepageCardRenderer.java b/src/com/android/settings/homepage/conditional/ConditionHomepageCardRenderer.java new file mode 100644 index 00000000000..6aa90ae558c --- /dev/null +++ b/src/com/android/settings/homepage/conditional/ConditionHomepageCardRenderer.java @@ -0,0 +1,137 @@ +/* + * 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.homepage.conditional; + +import android.content.Context; +import android.text.TextUtils; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.android.internal.logging.nano.MetricsProto; +import com.android.settings.R; +import com.android.settings.homepage.ControllerRendererPool; +import com.android.settings.homepage.HomepageCard; +import com.android.settings.homepage.HomepageCardRenderer; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; + +/** + * Card renderer for {@link ConditionCard}. + */ +public class ConditionHomepageCardRenderer implements HomepageCardRenderer { + + private final Context mContext; + private final ControllerRendererPool mControllerRendererPool; + + public ConditionHomepageCardRenderer(Context context, + ControllerRendererPool controllerRendererPool) { + mContext = context; + mControllerRendererPool = controllerRendererPool; + } + + @Override + public int getViewType() { + return R.layout.homepage_condition_tile; + } + + @Override + public RecyclerView.ViewHolder createViewHolder(View view) { + return new ConditionalCardHolder(view); + } + + @Override + public void bindView(RecyclerView.ViewHolder holder, HomepageCard homepageCard) { + final ConditionalCardHolder view = (ConditionalCardHolder) holder; + final ConditionCard card = (ConditionCard) homepageCard; + final MetricsFeatureProvider metricsFeatureProvider = FeatureFactory.getFactory( + mContext).getMetricsFeatureProvider(); + + metricsFeatureProvider.visible(mContext, MetricsProto.MetricsEvent.SETTINGS_HOMEPAGE, + card.getMetricsConstant()); + initializePrimaryClick(view, card, metricsFeatureProvider); + initializeView(view, card); + initializeActionButton(view, card, metricsFeatureProvider); + } + + private void initializePrimaryClick(ConditionalCardHolder view, ConditionCard card, + MetricsFeatureProvider metricsFeatureProvider) { + view.itemView.findViewById(R.id.content).setOnClickListener( + v -> { + metricsFeatureProvider.action(mContext, + MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_CLICK, + card.getMetricsConstant()); + mControllerRendererPool.getController(mContext, + card.getCardType()).onPrimaryClick(card); + }); + } + + private void initializeView(ConditionalCardHolder view, ConditionCard card) { + view.icon.setImageDrawable(card.getIconDrawable()); + view.title.setText(card.getTitleText()); + view.summary.setText(card.getSummaryText()); + + setViewVisibility(view.itemView, R.id.divider, false); + } + + private void initializeActionButton(ConditionalCardHolder view, ConditionCard card, + MetricsFeatureProvider metricsFeatureProvider) { + final CharSequence action = card.getActionText(); + final boolean hasButtons = !TextUtils.isEmpty(action); + setViewVisibility(view.itemView, R.id.buttonBar, hasButtons); + + final Button button = view.itemView.findViewById(R.id.first_action); + if (hasButtons) { + button.setVisibility(View.VISIBLE); + button.setText(action); + button.setOnClickListener(v -> { + final Context viewContext = v.getContext(); + metricsFeatureProvider.action( + viewContext, MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_BUTTON, + card.getMetricsConstant()); + mControllerRendererPool.getController(mContext, card.getCardType()).onActionClick( + card); + }); + } else { + button.setVisibility(View.GONE); + } + } + + private void setViewVisibility(View containerView, int viewId, boolean visible) { + View view = containerView.findViewById(viewId); + if (view != null) { + view.setVisibility(visible ? View.VISIBLE : View.GONE); + } + } + + public static class ConditionalCardHolder extends RecyclerView.ViewHolder { + + public final ImageView icon; + public final TextView title; + public final TextView summary; + + public ConditionalCardHolder(View itemView) { + super(itemView); + icon = itemView.findViewById(android.R.id.icon); + title = itemView.findViewById(android.R.id.title); + summary = itemView.findViewById(android.R.id.summary); + } + } +} diff --git a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardControllerTest.java new file mode 100644 index 00000000000..2b8ab00e796 --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardControllerTest.java @@ -0,0 +1,138 @@ +/* + * 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.homepage.conditional; + +import static org.mockito.ArgumentMatchers.any; +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.content.Context; +import android.graphics.drawable.Drawable; + +import com.android.settings.R; +import com.android.settings.homepage.HomepageCardUpdateListener; +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.util.ReflectionHelpers; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) +public class ConditionHomepageCardControllerTest { + + @Mock + private ConditionManager mConditionManager; + @Mock + private HomepageCardUpdateListener mListener; + private Context mContext; + private ConditionHomepageCardController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + mController = spy(new ConditionHomepageCardController(mContext)); + ReflectionHelpers.setField(mController, "mConditionManager", mConditionManager); + } + + @Test + public void onStart_shouldStartMonitoring() { + mController.onStart(); + + verify(mConditionManager).startMonitoringStateChange(); + } + + @Test + public void onStop_shouldStopMonitoring() { + mController.onStop(); + + verify(mConditionManager).stopMonitoringStateChange(); + } + + @Test + public void onConditionsChanged_listenerIsSet_shouldUpdateData() { + final FakeConditionalCard fakeConditionalCard = new FakeConditionalCard(mContext); + final List conditionalCards = new ArrayList<>(); + conditionalCards.add(fakeConditionalCard); + when(mConditionManager.getDisplayableCards()).thenReturn(conditionalCards); + mController.setHomepageCardUpdateListener(mListener); + + mController.onConditionsChanged(); + + verify(mController).onDataUpdated(any()); + } + + @Test + public void onConditionsChanged_listenerNotSet_shouldNotUpdateData() { + final FakeConditionalCard fakeConditionalCard = new FakeConditionalCard(mContext); + final List conditionalCards = new ArrayList<>(); + conditionalCards.add(fakeConditionalCard); + when(mConditionManager.getDisplayableCards()).thenReturn(conditionalCards); + + mController.onConditionsChanged(); + + verify(mController, never()).onDataUpdated(any()); + } + + private class FakeConditionalCard implements ConditionalCard { + + private final Context mContext; + + public FakeConditionalCard(Context context) { + mContext = context; + } + + @Override + public long getId() { + return 100; + } + + @Override + public CharSequence getActionText() { + return "action_text_test"; + } + + @Override + public int getMetricsConstant() { + return 1; + } + + @Override + public Drawable getIcon() { + return mContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp); + } + + @Override + public CharSequence getTitle() { + return "title_text_test"; + } + + @Override + public CharSequence getSummary() { + return "summary_text_test"; + } + } +} diff --git a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardRendererTest.java new file mode 100644 index 00000000000..663931a2eb0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionHomepageCardRendererTest.java @@ -0,0 +1,112 @@ +/* + * 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.homepage.conditional; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.settings.R; +import com.android.settings.homepage.ControllerRendererPool; +import com.android.settings.homepage.HomepageCard; +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; + +@RunWith(SettingsRobolectricTestRunner.class) +public class ConditionHomepageCardRendererTest { + + @Mock + private ControllerRendererPool mControllerRendererPool; + @Mock + private ConditionHomepageCardController mController; + private Context mContext; + private ConditionHomepageCardRenderer mRenderer; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + mRenderer = new ConditionHomepageCardRenderer(mContext, mControllerRendererPool); + } + + @Test + public void bindView_shouldSetListener() { + final int viewType = mRenderer.getViewType(); + final RecyclerView recyclerView = new RecyclerView(mContext); + recyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false); + final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view); + final View card = view.findViewById(R.id.content); + when(mControllerRendererPool.getController(mContext, + HomepageCard.CardType.CONDITIONAL)).thenReturn(mController); + + mRenderer.bindView(viewHolder, getHomepageCard()); + + assertThat(card).isNotNull(); + assertThat(card.hasOnClickListeners()).isTrue(); + } + + @Test + public void viewClick_shouldInvokeControllerPrimaryClick() { + final int viewType = mRenderer.getViewType(); + final RecyclerView recyclerView = new RecyclerView(mContext); + recyclerView.setLayoutManager(new LinearLayoutManager(mContext)); + final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false); + final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view); + final View card = view.findViewById(R.id.content); + when(mControllerRendererPool.getController(mContext, + HomepageCard.CardType.CONDITIONAL)).thenReturn(mController); + + mRenderer.bindView(viewHolder, getHomepageCard()); + + assertThat(card).isNotNull(); + card.performClick(); + + verify(mController).onPrimaryClick(any(HomepageCard.class)); + } + + private HomepageCard getHomepageCard() { + ConditionCard conditionCard = ((ConditionCard.Builder) new ConditionCard.Builder() + .setConditionId(123) + .setMetricsConstant(1) + .setActionText("test_action") + .setName("test_name") + .setCardType(HomepageCard.CardType.CONDITIONAL) + .setTitleText("test_title") + .setSummaryText("test_summary") + .setIconDrawable(mContext.getDrawable(R.drawable.ic_do_not_disturb_on_24dp)) + .setIsHalfWidth(true)) + .build(); + return conditionCard; + } +}