diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 3e50c91cd4f20678666ce67e292a985cb7d9ae1c..0b6e4009c4f7270f910461832def6f8c9cf16060 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -47,6 +47,7 @@ import com.android.systemui.statusbar.notification.SourceType; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableView; +import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor; import com.android.systemui.statusbar.notification.stack.AmbientState; import com.android.systemui.statusbar.notification.stack.AnimationProperties; import com.android.systemui.statusbar.notification.stack.ExpandableViewState; @@ -151,7 +152,11 @@ public class NotificationShelf extends ActivatableNotificationView { R.dimen.notification_corner_animation_distance); mEnableNotificationClipping = res.getBoolean(R.bool.notification_enable_clipping); - mShelfIcons.setInNotificationIconShelf(true); + if (NotificationIconContainerRefactor.isEnabled()) { + mShelfIcons.setOverrideIconColor(true); + } else { + mShelfIcons.setInNotificationIconShelf(true); + } if (!mShowNotificationShelf) { setVisibility(GONE); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 3a4ad0e79994f30a79d5d35c457adc3446b3296b..3bf8057aece2b8d817a48c5cc6df1c5ea0cd3999 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -59,7 +59,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.util.ContrastColorUtil; import com.android.systemui.res.R; -import com.android.systemui.statusbar.notification.NotificationIconDozeHelper; +import com.android.systemui.statusbar.notification.NotificationDozeHelper; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.util.drawable.DrawableSize; @@ -174,7 +174,7 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi animation.getAnimatedFraction()); setColorInternal(newColor); }; - private final NotificationIconDozeHelper mDozer; + private final NotificationDozeHelper mDozer; private int mContrastedDrawableColor; private int mCachedContrastBackgroundColor = NO_COLOR; private float[] mMatrix; @@ -192,7 +192,7 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi public StatusBarIconView(Context context, String slot, StatusBarNotification sbn, boolean blocked) { super(context); - mDozer = new NotificationIconDozeHelper(context); + mDozer = new NotificationDozeHelper(); mBlocked = blocked; mSlot = slot; mNumberPain = new Paint(); @@ -712,7 +712,6 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi setColorInternal(color); updateContrastedStaticColor(); mIconColor = color; - mDozer.setColor(color); } private void setColorInternal(int color) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java index dc0eb7b4aab34d92741eb70af9348e9512891db4..2f9917fe33fe4c22bb6dc277bed79555407c362f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java @@ -36,26 +36,6 @@ public class NotificationDozeHelper { private static final int DOZE_ANIMATOR_TAG = R.id.doze_intensity_tag; private final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix(); - public void fadeGrayscale(final ImageView target, final boolean dark, long delay) { - startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - updateGrayscale(target, (float) animation.getAnimatedValue()); - } - }, dark, delay, new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (!dark) { - target.setColorFilter(null); - } - } - }); - } - - public void updateGrayscale(ImageView target, boolean dark) { - updateGrayscale(target, dark ? 1 : 0); - } - public void updateGrayscale(ImageView target, float darkAmount) { if (darkAmount > 0) { updateGrayscaleMatrix(darkAmount); @@ -66,7 +46,7 @@ public class NotificationDozeHelper { } // TODO: this should be using StatusBarStateController#getDozeAmount - public void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener, + private void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener, boolean dark, long delay, Animator.AnimatorListener listener) { float startIntensity = dark ? 0f : 1f; float endIntensity = dark ? 1f : 0f; @@ -81,11 +61,6 @@ public class NotificationDozeHelper { animator.start(); } - public void setDozing(Consumer<Float> listener, boolean dozing, - boolean animate, long delay, View view) { - setDozing(listener, dozing, animate, delay, view, /* endRunnable= */ null); - } - public void setDozing(Consumer<Float> listener, boolean dozing, boolean animate, long delay, View view, @Nullable Runnable endRunnable) { if (animate) { @@ -118,11 +93,7 @@ public class NotificationDozeHelper { } } - public void updateGrayscaleMatrix(float intensity) { + private void updateGrayscaleMatrix(float intensity) { mGrayscaleColorMatrix.setSaturation(1 - intensity); } - - public ColorMatrix getGrayscaleColorMatrix() { - return mGrayscaleColorMatrix; - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java deleted file mode 100644 index 552bfb288d7a9d0e17633bbb238fe8d2971761b1..0000000000000000000000000000000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationIconDozeHelper.java +++ /dev/null @@ -1,105 +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.systemui.statusbar.notification; - -import android.annotation.Nullable; -import android.content.Context; -import android.graphics.Color; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffColorFilter; -import android.graphics.drawable.Drawable; -import android.widget.ImageView; - -import com.android.systemui.res.R; - -public class NotificationIconDozeHelper extends NotificationDozeHelper { - - private final int mImageDarkAlpha; - private final int mImageDarkColor = 0xffffffff; - - @Nullable - private PorterDuffColorFilter mImageColorFilter = null; - - private int mColor = Color.BLACK; - - public NotificationIconDozeHelper(Context ctx) { - mImageDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha); - } - - public void setColor(int color) { - mColor = color; - } - - public void setImageDark(ImageView target, boolean dark, boolean fade, long delay, - boolean useGrayscale) { - if (fade) { - if (!useGrayscale) { - fadeImageColorFilter(target, dark, delay); - fadeImageAlpha(target, dark, delay); - } else { - fadeGrayscale(target, dark, delay); - } - } else { - if (!useGrayscale) { - updateImageColorFilter(target, dark); - updateImageAlpha(target, dark); - } else { - updateGrayscale(target, dark); - } - } - } - - private void fadeImageColorFilter(final ImageView target, boolean dark, long delay) { - startIntensityAnimation(animation -> { - updateImageColorFilter(target, (Float) animation.getAnimatedValue()); - }, dark, delay, null /* listener */); - } - - private void fadeImageAlpha(final ImageView target, boolean dark, long delay) { - startIntensityAnimation(animation -> { - float t = (float) animation.getAnimatedValue(); - target.setImageAlpha((int) (255 * (1f - t) + mImageDarkAlpha * t)); - }, dark, delay, null /* listener */); - } - - private void updateImageColorFilter(ImageView target, boolean dark) { - updateImageColorFilter(target, dark ? 1f : 0f); - } - - private void updateImageColorFilter(ImageView target, float intensity) { - int color = NotificationUtils.interpolateColors(mColor, mImageDarkColor, intensity); - if (mImageColorFilter == null || mImageColorFilter.getColor() != color) { - mImageColorFilter = new PorterDuffColorFilter(color, Mode.SRC_ATOP); - } - Drawable imageDrawable = target.getDrawable(); - - // Also, the notification might have been modified during the animation, so background - // might be null here. - if (imageDrawable != null) { - Drawable d = imageDrawable.mutate(); - // DrawableContainer ignores the color filter if it's already set, so clear it first to - // get it set and invalidated properly. - d.setColorFilter(null); - d.setColorFilter(mImageColorFilter); - } - } - - private void updateImageAlpha(ImageView target, boolean dark) { - target.setImageAlpha(dark ? mImageDarkAlpha : 255); - } - -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java index 75a697f17e6ffb70d953ea14f13b2292262a1ead..01f3b63280a259bd1c871a2f3752feb78b716d51 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java @@ -132,13 +132,16 @@ public class NotificationIconContainer extends ViewGroup { } }.setDuration(CONTENT_FADE_DURATION); + // TODO(b/278765923): Replace these with domain-agnostic state /* Maximum number of icons on AOD when also showing overflow dot. */ private int mMaxIconsOnAod; - /* Maximum number of icons in short shelf on lockscreen when also showing overflow dot. */ private int mMaxIconsOnLockscreen; /* Maximum number of icons in the status bar when also showing overflow dot. */ private int mMaxStaticIcons; + private boolean mDozing; + private boolean mOnLockScreen; + private boolean mOverrideIconColor; private boolean mIsStaticLayout = true; private final HashMap<View, IconState> mIconStates = new HashMap<>(); @@ -147,9 +150,6 @@ public class NotificationIconContainer extends ViewGroup { private int mActualLayoutWidth = NO_VALUE; private float mActualPaddingEnd = NO_VALUE; private float mActualPaddingStart = NO_VALUE; - private boolean mDozing; - private boolean mOnLockScreen; - private boolean mInNotificationIconShelf; private boolean mChangingViewPositions; private int mAddAnimationStartIndex = -1; private int mCannedAnimationStartIndex = -1; @@ -284,7 +284,7 @@ public class NotificationIconContainer extends ViewGroup { public String toString() { return "NotificationIconContainer(" + "dozing=" + mDozing + " onLockScreen=" + mOnLockScreen - + " inNotificationIconShelf=" + mInNotificationIconShelf + + " overrideIconColor=" + mOverrideIconColor + " speedBumpIndex=" + mSpeedBumpIndex + " themedTextColorPrimary=#" + Integer.toHexString(mThemedTextColorPrimary) + ')'; } @@ -739,8 +739,15 @@ public class NotificationIconContainer extends ViewGroup { mOnLockScreen = onLockScreen; } + @Deprecated public void setInNotificationIconShelf(boolean inShelf) { - mInNotificationIconShelf = inShelf; + NotificationIconContainerRefactor.assertInLegacyMode(); + mOverrideIconColor = inShelf; + } + + public void setOverrideIconColor(boolean override) { + if (NotificationIconContainerRefactor.isUnexpectedlyInLegacyMode()) return; + mOverrideIconColor = override; } public class IconState extends ViewState { @@ -858,7 +865,7 @@ public class NotificationIconContainer extends ViewGroup { } } icon.setVisibleState(visibleState, animationsAllowed); - icon.setIconColor(mInNotificationIconShelf ? mThemedTextColorPrimary : iconColor, + icon.setIconColor(mOverrideIconColor ? mThemedTextColorPrimary : iconColor, needsCannedAnimation && animationsAllowed); if (animate) { animateTo(icon, animationProperties); diff --git a/packages/SystemUI/tests/src/com/android/SysUITestModule.kt b/packages/SystemUI/tests/src/com/android/SysUITestModule.kt index c4b43e1cbe77238642e56686a3ea66a63f9200e6..97e43ad91f532f24744444a08fad85cdb599a1d5 100644 --- a/packages/SystemUI/tests/src/com/android/SysUITestModule.kt +++ b/packages/SystemUI/tests/src/com/android/SysUITestModule.kt @@ -24,11 +24,21 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestableContext import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.broadcast.FakeBroadcastDispatcher +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.coroutines.collectValues import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import dagger.Binds import dagger.Module import dagger.Provides +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest @Module( includes = @@ -64,3 +74,35 @@ interface SysUITestModule { test.fakeBroadcastDispatcher } } + +interface SysUITestComponent<out T> { + val testScope: TestScope + val underTest: T +} + +@OptIn(ExperimentalCoroutinesApi::class) +fun <T : SysUITestComponent<*>> T.runTest(block: suspend T.() -> Unit): Unit = + testScope.runTest { + // Access underTest immediately to force Dagger to instantiate it prior to the test running + underTest + runCurrent() + block() + } + +@OptIn(ExperimentalCoroutinesApi::class) +fun SysUITestComponent<*>.runCurrent() = testScope.runCurrent() + +fun <T> SysUITestComponent<*>.collectLastValue( + flow: Flow<T>, + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, +) = testScope.collectLastValue(flow, context, start) + +fun <T> SysUITestComponent<*>.collectValues( + flow: Flow<T>, + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, +) = testScope.collectValues(flow, context, start) + +val SysUITestComponent<*>.backgroundScope + get() = testScope.backgroundScope diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt index 8c26776a1ef8a67c29b8708272805adbc016790c..d2b81e06c0e5eab37dfc9f49861f8453bbc3fc9a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt @@ -17,7 +17,10 @@ package com.android.systemui.biometrics import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule +import com.android.runCurrent +import com.android.runTest import com.android.systemui.SysuiTestCase import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FakeFeatureFlagsClassicModule @@ -26,10 +29,6 @@ import com.android.systemui.shade.data.repository.FakeShadeRepository import com.android.systemui.user.domain.UserDomainLayerModule import dagger.BindsInstance import dagger.Component -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.mockito.Mock @@ -38,9 +37,29 @@ import org.mockito.Mockito.verifyZeroInteractions import org.mockito.MockitoAnnotations @SmallTest -@OptIn(ExperimentalCoroutinesApi::class) class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent : SysUITestComponent<AuthDialogPanelInteractionDetector> { + + val shadeRepository: FakeShadeRepository + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + featureFlags: FakeFeatureFlagsClassicModule, + ): TestComponent + } + } + private val testComponent: TestComponent = DaggerAuthDialogPanelInteractionDetectorTest_TestComponent.factory() .create( @@ -52,11 +71,9 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { }, ) - @Mock private lateinit var action: Runnable + private val detector: AuthDialogPanelInteractionDetector = testComponent.underTest - private val testScope = testComponent.testScope - private val shadeRepository = testComponent.shadeRepository - private val detector = testComponent.detector + @Mock private lateinit var action: Runnable @Before fun setUp() { @@ -65,7 +82,7 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { @Test fun enableDetector_expand_shouldRunAction() = - testScope.runTest { + testComponent.runTest { // GIVEN shade is closed and detector is enabled shadeRepository.setLegacyShadeExpansion(0f) detector.enable(action) @@ -82,7 +99,7 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { @Test fun enableDetector_shadeExpandImmediate_shouldNotPostRunnable() = - testScope.runTest { + testComponent.runTest { // GIVEN shade is closed and detector is enabled shadeRepository.setLegacyShadeExpansion(0f) detector.enable(action) @@ -94,14 +111,11 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { // THEN action not run verifyZeroInteractions(action) - - // Clean up job - detector.disable() } @Test fun disableDetector_shouldNotPostRunnable() = - testScope.runTest { + testComponent.runTest { // GIVEN shade is closed and detector is enabled shadeRepository.setLegacyShadeExpansion(0f) detector.enable(action) @@ -109,6 +123,7 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { // WHEN detector is disabled and shade opens detector.disable() + runCurrent() shadeRepository.setLegacyShadeTracking(true) shadeRepository.setLegacyShadeExpansion(.5f) runCurrent() @@ -119,7 +134,7 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { @Test fun enableDetector_beginCollapse_shouldNotPostRunnable() = - testScope.runTest { + testComponent.runTest { // GIVEN shade is open and detector is enabled shadeRepository.setLegacyShadeExpansion(1f) detector.enable(action) @@ -131,31 +146,5 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() { // THEN action not run verifyZeroInteractions(action) - - // Clean up job - detector.disable() } - - @SysUISingleton - @Component( - modules = - [ - SysUITestModule::class, - UserDomainLayerModule::class, - ] - ) - interface TestComponent { - - val detector: AuthDialogPanelInteractionDetector - val shadeRepository: FakeShadeRepository - val testScope: TestScope - - @Component.Factory - interface Factory { - fun create( - @BindsInstance test: SysuiTestCase, - featureFlags: FakeFeatureFlagsClassicModule, - ): TestComponent - } - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt index 4a1386e21e2aef66c58238151a37f24191039fa8..985b6fde4c63f2e1e2ffca4f7d18ab4f8136bd67 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt @@ -21,8 +21,12 @@ package com.android.systemui.keyguard.ui.viewmodel import android.view.View import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule import com.android.TestMocksModule +import com.android.collectLastValue +import com.android.runCurrent +import com.android.runTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue @@ -319,12 +323,10 @@ class KeyguardRootViewModelTestWithFakes : SysuiTestCase() { @Component(modules = [SysUITestModule::class]) @SysUISingleton - interface TestComponent { - val underTest: KeyguardRootViewModel + interface TestComponent : SysUITestComponent<KeyguardRootViewModel> { val deviceEntryRepository: FakeDeviceEntryRepository val notifsKeyguardRepository: FakeNotificationsKeyguardViewStateRepository val repository: FakeKeyguardRepository - val testScope: TestScope val transitionRepository: FakeKeyguardTransitionRepository @Component.Factory @@ -356,28 +358,25 @@ class KeyguardRootViewModelTestWithFakes : SysuiTestCase() { TestMocksModule( dozeParameters = dozeParams, screenOffAnimationController = screenOffAnimController, - ) + ), ) - .run { + .runTest { reset(clockController) underTest.clockControllerProvider = Provider { clockController } - testScope.runTest { - runCurrent() - block() - } + block() } @Test fun iconContainer_isNotVisible_notOnKeyguard_dontShowAodIconsWhenShade() = runTest { - val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible) - testScope.runCurrent() + val isVisible by collectLastValue(underTest.isNotifIconContainerVisible) + runCurrent() transitionRepository.sendTransitionSteps( from = KeyguardState.OFF, to = KeyguardState.GONE, testScope, ) whenever(screenOffAnimController.shouldShowAodIconsWhenShade()).thenReturn(false) - testScope.runCurrent() + runCurrent() assertThat(isVisible?.value).isFalse() assertThat(isVisible?.isAnimating).isFalse() @@ -385,33 +384,33 @@ class KeyguardRootViewModelTestWithFakes : SysuiTestCase() { @Test fun iconContainer_isVisible_bypassEnabled() = runTest { - val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible) - testScope.runCurrent() + val isVisible by collectLastValue(underTest.isNotifIconContainerVisible) + runCurrent() deviceEntryRepository.setBypassEnabled(true) - testScope.runCurrent() + runCurrent() assertThat(isVisible?.value).isTrue() } @Test fun iconContainer_isNotVisible_pulseExpanding_notBypassing() = runTest { - val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible) - testScope.runCurrent() + val isVisible by collectLastValue(underTest.isNotifIconContainerVisible) + runCurrent() notifsKeyguardRepository.setPulseExpanding(true) deviceEntryRepository.setBypassEnabled(false) - testScope.runCurrent() + runCurrent() assertThat(isVisible?.value).isEqualTo(false) } @Test fun iconContainer_isVisible_notifsFullyHidden_bypassEnabled() = runTest { - val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible) - testScope.runCurrent() + val isVisible by collectLastValue(underTest.isNotifIconContainerVisible) + runCurrent() notifsKeyguardRepository.setPulseExpanding(false) deviceEntryRepository.setBypassEnabled(true) notifsKeyguardRepository.setNotificationsFullyHidden(true) - testScope.runCurrent() + runCurrent() assertThat(isVisible?.value).isTrue() assertThat(isVisible?.isAnimating).isTrue() @@ -419,13 +418,13 @@ class KeyguardRootViewModelTestWithFakes : SysuiTestCase() { @Test fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled_aodDisabled() = runTest { - val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible) - testScope.runCurrent() + val isVisible by collectLastValue(underTest.isNotifIconContainerVisible) + runCurrent() notifsKeyguardRepository.setPulseExpanding(false) deviceEntryRepository.setBypassEnabled(false) whenever(dozeParams.alwaysOn).thenReturn(false) notifsKeyguardRepository.setNotificationsFullyHidden(true) - testScope.runCurrent() + runCurrent() assertThat(isVisible?.value).isTrue() assertThat(isVisible?.isAnimating).isFalse() @@ -433,14 +432,14 @@ class KeyguardRootViewModelTestWithFakes : SysuiTestCase() { @Test fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled_displayNeedsBlanking() = runTest { - val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible) - testScope.runCurrent() + val isVisible by collectLastValue(underTest.isNotifIconContainerVisible) + runCurrent() notifsKeyguardRepository.setPulseExpanding(false) deviceEntryRepository.setBypassEnabled(false) whenever(dozeParams.alwaysOn).thenReturn(true) whenever(dozeParams.displayNeedsBlanking).thenReturn(true) notifsKeyguardRepository.setNotificationsFullyHidden(true) - testScope.runCurrent() + runCurrent() assertThat(isVisible?.value).isTrue() assertThat(isVisible?.isAnimating).isFalse() @@ -448,14 +447,14 @@ class KeyguardRootViewModelTestWithFakes : SysuiTestCase() { @Test fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled() = runTest { - val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible) - testScope.runCurrent() + val isVisible by collectLastValue(underTest.isNotifIconContainerVisible) + runCurrent() notifsKeyguardRepository.setPulseExpanding(false) deviceEntryRepository.setBypassEnabled(false) whenever(dozeParams.alwaysOn).thenReturn(true) whenever(dozeParams.displayNeedsBlanking).thenReturn(false) notifsKeyguardRepository.setNotificationsFullyHidden(true) - testScope.runCurrent() + runCurrent() assertThat(isVisible?.value).isTrue() assertThat(isVisible?.isAnimating).isTrue() @@ -463,18 +462,18 @@ class KeyguardRootViewModelTestWithFakes : SysuiTestCase() { @Test fun isIconContainerVisible_stopAnimation() = runTest { - val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible) - testScope.runCurrent() + val isVisible by collectLastValue(underTest.isNotifIconContainerVisible) + runCurrent() notifsKeyguardRepository.setPulseExpanding(false) deviceEntryRepository.setBypassEnabled(false) whenever(dozeParams.alwaysOn).thenReturn(true) whenever(dozeParams.displayNeedsBlanking).thenReturn(false) notifsKeyguardRepository.setNotificationsFullyHidden(true) - testScope.runCurrent() + runCurrent() assertThat(isVisible?.isAnimating).isEqualTo(true) isVisible?.stopAnimating() - testScope.runCurrent() + runCurrent() assertThat(isVisible?.isAnimating).isEqualTo(false) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt index 8b8a6258589885fe7f3c903a7d0d5eb58d6232c1..ff7443f10bf3fb75e05c3cc8ad529b3dbd84f348 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt @@ -22,11 +22,14 @@ import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS import android.content.pm.UserInfo import android.os.UserManager import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule import com.android.TestMocksModule +import com.android.collectLastValue +import com.android.runCurrent +import com.android.runTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository -import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FakeFeatureFlagsClassicModule import com.android.systemui.flags.Flags @@ -54,75 +57,70 @@ import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvision import com.android.systemui.user.data.model.UserSwitcherSettingsModel import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.user.domain.UserDomainLayerModule +import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test -import org.mockito.Mock -import org.mockito.MockitoAnnotations @SmallTest -@OptIn(ExperimentalCoroutinesApi::class) class ShadeInteractorTest : SysuiTestCase() { - @Mock private lateinit var dozeParameters: DozeParameters - - private lateinit var testComponent: TestComponent - - private val configurationRepository - get() = testComponent.configurationRepository - private val deviceProvisioningRepository - get() = testComponent.deviceProvisioningRepository - private val disableFlagsRepository - get() = testComponent.disableFlagsRepository - private val keyguardRepository - get() = testComponent.keyguardRepository - private val keyguardTransitionRepository - get() = testComponent.keygaurdTransitionRepository - private val powerRepository - get() = testComponent.powerRepository - private val sceneInteractor - get() = testComponent.sceneInteractor - private val shadeRepository - get() = testComponent.shadeRepository - private val testScope - get() = testComponent.testScope - private val userRepository - get() = testComponent.userRepository - private val userSetupRepository - get() = testComponent.userSetupRepository - - private lateinit var underTest: ShadeInteractor + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent : SysUITestComponent<ShadeInteractor> { + + val configurationRepository: FakeConfigurationRepository + val deviceProvisioningRepository: FakeDeviceProvisioningRepository + val disableFlagsRepository: FakeDisableFlagsRepository + val keyguardRepository: FakeKeyguardRepository + val keyguardTransitionRepository: FakeKeyguardTransitionRepository + val powerRepository: FakePowerRepository + val sceneInteractor: SceneInteractor + val shadeRepository: FakeShadeRepository + val userRepository: FakeUserRepository + val userSetupRepository: FakeUserSetupRepository + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + featureFlags: FakeFeatureFlagsClassicModule, + mocks: TestMocksModule, + ): TestComponent + } + } + + private val dozeParameters: DozeParameters = mock() + + private val testComponent: TestComponent = + DaggerShadeInteractorTest_TestComponent.factory() + .create( + test = this, + featureFlags = + FakeFeatureFlagsClassicModule { + set(Flags.FACE_AUTH_REFACTOR, false) + set(Flags.FULL_SCREEN_USER_SWITCHER, true) + }, + mocks = + TestMocksModule( + dozeParameters = dozeParameters, + ), + ) @Before fun setUp() { - MockitoAnnotations.initMocks(this) - - testComponent = - DaggerShadeInteractorTest_TestComponent.factory() - .create( - test = this, - featureFlags = - FakeFeatureFlagsClassicModule { - set(Flags.FACE_AUTH_REFACTOR, false) - set(Flags.FULL_SCREEN_USER_SWITCHER, true) - }, - mocks = - TestMocksModule( - dozeParameters = dozeParameters, - ), - ) - underTest = testComponent.underTest - runBlocking { val userInfos = listOf( @@ -136,14 +134,16 @@ class ShadeInteractorTest : SysuiTestCase() { UserManager.USER_TYPE_FULL_SYSTEM, ), ) - userRepository.setUserInfos(userInfos) - userRepository.setSelectedUserInfo(userInfos[0]) + testComponent.apply { + userRepository.setUserInfos(userInfos) + userRepository.setSelectedUserInfo(userInfos[0]) + } } } @Test fun isShadeEnabled_matchesDisableFlagsRepo() = - testScope.runTest { + testComponent.runTest { val actual by collectLastValue(underTest.isShadeEnabled) disableFlagsRepository.disableFlags.value = @@ -157,7 +157,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_deviceNotProvisioned_false() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setDeviceProvisioned(false) val actual by collectLastValue(underTest.isExpandToQsEnabled) @@ -167,7 +167,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_userNotSetupAndSimpleUserSwitcher_false() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setDeviceProvisioned(true) userSetupRepository.setUserSetup(false) @@ -180,7 +180,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_shadeNotEnabled_false() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setDeviceProvisioned(true) userSetupRepository.setUserSetup(true) @@ -196,7 +196,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_quickSettingsNotEnabled_false() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setDeviceProvisioned(true) userSetupRepository.setUserSetup(true) @@ -211,7 +211,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_dozing_false() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setDeviceProvisioned(true) userSetupRepository.setUserSetup(true) disableFlagsRepository.disableFlags.value = @@ -228,7 +228,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_userSetup_true() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setDeviceProvisioned(true) keyguardRepository.setIsDozing(false) disableFlagsRepository.disableFlags.value = @@ -245,7 +245,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_notSimpleUserSwitcher_true() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setDeviceProvisioned(true) keyguardRepository.setIsDozing(false) disableFlagsRepository.disableFlags.value = @@ -262,7 +262,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_respondsToDozingUpdates() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setDeviceProvisioned(true) keyguardRepository.setIsDozing(false) disableFlagsRepository.disableFlags.value = @@ -290,7 +290,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_respondsToDisableUpdates() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setDeviceProvisioned(true) keyguardRepository.setIsDozing(false) disableFlagsRepository.disableFlags.value = @@ -322,7 +322,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isExpandToQsEnabled_respondsToUserUpdates() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setDeviceProvisioned(true) keyguardRepository.setIsDozing(false) disableFlagsRepository.disableFlags.value = @@ -351,7 +351,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun fullShadeExpansionWhenShadeLocked() = - testScope.runTest { + testComponent.runTest { val actual by collectLastValue(underTest.shadeExpansion) keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED) @@ -362,7 +362,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun fullShadeExpansionWhenStatusBarStateIsNotShadeLocked() = - testScope.runTest { + testComponent.runTest { val actual by collectLastValue(underTest.shadeExpansion) keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD) @@ -376,7 +376,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun shadeExpansionWhenInSplitShadeAndQsExpanded() = - testScope.runTest { + testComponent.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is enabled and QS is expanded @@ -393,7 +393,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun shadeExpansionWhenNotInSplitShadeAndQsExpanded() = - testScope.runTest { + testComponent.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is not enabled and QS is expanded @@ -409,7 +409,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun shadeExpansionWhenNotInSplitShadeAndQsCollapsed() = - testScope.runTest { + testComponent.runTest { val actual by collectLastValue(underTest.shadeExpansion) // WHEN split shade is not enabled and QS is expanded @@ -423,7 +423,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun anyExpansion_shadeGreater() = - testScope.runTest() { + testComponent.runTest() { // WHEN shade is more expanded than QS shadeRepository.setLegacyShadeExpansion(.5f) shadeRepository.setQsExpansion(0f) @@ -435,7 +435,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun anyExpansion_qsGreater() = - testScope.runTest() { + testComponent.runTest() { // WHEN qs is more expanded than shade shadeRepository.setLegacyShadeExpansion(0f) shadeRepository.setQsExpansion(.5f) @@ -447,7 +447,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun lockscreenShadeExpansion_idle_onScene() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val key = SceneKey.Shade val expansion = underTest.sceneBasedExpansion(sceneInteractor, key) @@ -464,7 +464,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun lockscreenShadeExpansion_idle_onDifferentScene() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val expansion = underTest.sceneBasedExpansion(sceneInteractor, SceneKey.Shade) val expansionAmount by collectLastValue(expansion) @@ -482,7 +482,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun lockscreenShadeExpansion_transitioning_toScene() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val key = SceneKey.QuickSettings val expansion = underTest.sceneBasedExpansion(sceneInteractor, key) @@ -520,7 +520,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun lockscreenShadeExpansion_transitioning_fromScene() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val key = SceneKey.QuickSettings val expansion = underTest.sceneBasedExpansion(sceneInteractor, key) @@ -558,7 +558,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun lockscreenShadeExpansion_transitioning_toAndFromDifferentScenes() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an expansion flow based on transitions to and from a scene val expansion = underTest.sceneBasedExpansion(sceneInteractor, SceneKey.QuickSettings) val expansionAmount by collectLastValue(expansion) @@ -595,7 +595,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun userInteractingWithShade_shadeDraggedUpAndDown() = - testScope.runTest() { + testComponent.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade collapsed and not tracking input shadeRepository.setLegacyShadeExpansion(0f) @@ -651,7 +651,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun userInteractingWithShade_shadeExpanded() = - testScope.runTest() { + testComponent.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade collapsed and not tracking input shadeRepository.setLegacyShadeExpansion(0f) @@ -686,7 +686,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun userInteractingWithShade_shadePartiallyExpanded() = - testScope.runTest() { + testComponent.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade collapsed and not tracking input shadeRepository.setLegacyShadeExpansion(0f) @@ -727,7 +727,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun userInteractingWithShade_shadeCollapsed() = - testScope.runTest() { + testComponent.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithShade) // GIVEN shade expanded and not tracking input shadeRepository.setLegacyShadeExpansion(1f) @@ -762,7 +762,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun userInteractingWithQs_qsDraggedUpAndDown() = - testScope.runTest() { + testComponent.runTest() { val actual by collectLastValue(underTest.isUserInteractingWithQs) // GIVEN qs collapsed and not tracking input shadeRepository.setQsExpansion(0f) @@ -817,7 +817,7 @@ class ShadeInteractorTest : SysuiTestCase() { } @Test fun userInteracting_idle() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an interacting flow based on transitions to and from a scene val key = SceneKey.Shade val interactingFlow = underTest.sceneBasedInteracting(sceneInteractor, key) @@ -834,7 +834,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun userInteracting_transitioning_toScene_programmatic() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an interacting flow based on transitions to and from a scene val key = SceneKey.QuickSettings val interactingFlow = underTest.sceneBasedInteracting(sceneInteractor, key) @@ -872,7 +872,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun userInteracting_transitioning_toScene_userInputDriven() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an interacting flow based on transitions to and from a scene val key = SceneKey.QuickSettings val interactingFlow = underTest.sceneBasedInteracting(sceneInteractor, key) @@ -910,7 +910,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun userInteracting_transitioning_fromScene_programmatic() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an interacting flow based on transitions to and from a scene val key = SceneKey.QuickSettings val interactingFlow = underTest.sceneBasedInteracting(sceneInteractor, key) @@ -948,7 +948,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun userInteracting_transitioning_fromScene_userInputDriven() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an interacting flow based on transitions to and from a scene val key = SceneKey.QuickSettings val interactingFlow = underTest.sceneBasedInteracting(sceneInteractor, key) @@ -986,7 +986,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun userInteracting_transitioning_toAndFromDifferentScenes() = - testScope.runTest() { + testComponent.runTest() { // GIVEN an interacting flow based on transitions to and from a scene val interactingFlow = underTest.sceneBasedInteracting(sceneInteractor, SceneKey.Shade) val interacting by collectLastValue(interactingFlow) @@ -1011,7 +1011,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isShadeTouchable_isFalse_whenFrpIsActive() = - testScope.runTest { + testComponent.runTest { deviceProvisioningRepository.setFactoryResetProtectionActive(true) keyguardTransitionRepository.sendTransitionStep( TransitionStep( @@ -1025,7 +1025,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isShadeTouchable_isFalse_whenDeviceAsleepAndNotPulsing() = - testScope.runTest { + testComponent.runTest { powerRepository.updateWakefulness( rawState = WakefulnessState.ASLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -1052,7 +1052,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isShadeTouchable_isTrue_whenDeviceAsleepAndPulsing() = - testScope.runTest { + testComponent.runTest { powerRepository.updateWakefulness( rawState = WakefulnessState.ASLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -1079,7 +1079,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isShadeTouchable_isFalse_whenStartingToSleepAndNotControlScreenOff() = - testScope.runTest { + testComponent.runTest { powerRepository.updateWakefulness( rawState = WakefulnessState.STARTING_TO_SLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -1101,7 +1101,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isShadeTouchable_isTrue_whenStartingToSleepAndControlScreenOff() = - testScope.runTest { + testComponent.runTest { powerRepository.updateWakefulness( rawState = WakefulnessState.STARTING_TO_SLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -1123,7 +1123,7 @@ class ShadeInteractorTest : SysuiTestCase() { @Test fun isShadeTouchable_isTrue_whenNotAsleep() = - testScope.runTest { + testComponent.runTest { powerRepository.updateWakefulness( rawState = WakefulnessState.AWAKE, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -1138,38 +1138,4 @@ class ShadeInteractorTest : SysuiTestCase() { runCurrent() assertThat(isShadeTouchable).isTrue() } - - @SysUISingleton - @Component( - modules = - [ - SysUITestModule::class, - UserDomainLayerModule::class, - ] - ) - interface TestComponent { - - val underTest: ShadeInteractor - - val configurationRepository: FakeConfigurationRepository - val deviceProvisioningRepository: FakeDeviceProvisioningRepository - val disableFlagsRepository: FakeDisableFlagsRepository - val keyguardRepository: FakeKeyguardRepository - val keygaurdTransitionRepository: FakeKeyguardTransitionRepository - val powerRepository: FakePowerRepository - val sceneInteractor: SceneInteractor - val shadeRepository: FakeShadeRepository - val testScope: TestScope - val userRepository: FakeUserRepository - val userSetupRepository: FakeUserSetupRepository - - @Component.Factory - interface Factory { - fun create( - @BindsInstance test: SysuiTestCase, - featureFlags: FakeFeatureFlagsClassicModule, - mocks: TestMocksModule, - ): TestComponent - } - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/data/repository/NotificationsKeyguardViewStateRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/data/repository/NotificationsKeyguardViewStateRepositoryTest.kt index 2f8f3bb14ee5fb016035560c4ce015b2a6a3d186..d47993793fc08616667b5fcaebf3db496df99cee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/data/repository/NotificationsKeyguardViewStateRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/data/repository/NotificationsKeyguardViewStateRepositoryTest.kt @@ -13,14 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@file:OptIn(ExperimentalCoroutinesApi::class) package com.android.systemui.statusbar.notification.data.repository import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule +import com.android.collectLastValue +import com.android.runCurrent +import com.android.runTest import com.android.systemui.SysuiTestCase -import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator import com.android.systemui.util.mockito.whenever @@ -28,75 +30,59 @@ import com.android.systemui.util.mockito.withArgCaptor import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Test import org.mockito.Mockito.verify @SmallTest class NotificationsKeyguardViewStateRepositoryTest : SysuiTestCase() { + @SysUISingleton + @Component(modules = [SysUITestModule::class]) + interface TestComponent : SysUITestComponent<NotificationsKeyguardViewStateRepositoryImpl> { + + val mockWakeUpCoordinator: NotificationWakeUpCoordinator + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + ): TestComponent + } + } + private val testComponent: TestComponent = DaggerNotificationsKeyguardViewStateRepositoryTest_TestComponent.factory() .create(test = this) @Test fun areNotifsFullyHidden_reflectsWakeUpCoordinator() = - with(testComponent) { - testScope.runTest { - whenever(mockWakeUpCoordinator.notificationsFullyHidden).thenReturn(false) - val notifsFullyHidden by collectLastValue(underTest.areNotificationsFullyHidden) - runCurrent() + testComponent.runTest { + whenever(mockWakeUpCoordinator.notificationsFullyHidden).thenReturn(false) + val notifsFullyHidden by collectLastValue(underTest.areNotificationsFullyHidden) + runCurrent() - assertThat(notifsFullyHidden).isFalse() + assertThat(notifsFullyHidden).isFalse() - withArgCaptor { verify(mockWakeUpCoordinator).addListener(capture()) } - .onFullyHiddenChanged(true) - runCurrent() + withArgCaptor { verify(mockWakeUpCoordinator).addListener(capture()) } + .onFullyHiddenChanged(true) + runCurrent() - assertThat(notifsFullyHidden).isTrue() - } + assertThat(notifsFullyHidden).isTrue() } @Test fun isPulseExpanding_reflectsWakeUpCoordinator() = - with(testComponent) { - testScope.runTest { - whenever(mockWakeUpCoordinator.isPulseExpanding()).thenReturn(false) - val isPulseExpanding by collectLastValue(underTest.isPulseExpanding) - runCurrent() + testComponent.runTest { + whenever(mockWakeUpCoordinator.isPulseExpanding()).thenReturn(false) + val isPulseExpanding by collectLastValue(underTest.isPulseExpanding) + runCurrent() - assertThat(isPulseExpanding).isFalse() + assertThat(isPulseExpanding).isFalse() - withArgCaptor { verify(mockWakeUpCoordinator).addListener(capture()) } - .onPulseExpansionChanged(true) - runCurrent() + withArgCaptor { verify(mockWakeUpCoordinator).addListener(capture()) } + .onPulseExpansionChanged(true) + runCurrent() - assertThat(isPulseExpanding).isTrue() - } + assertThat(isPulseExpanding).isTrue() } - - @SysUISingleton - @Component( - modules = - [ - SysUITestModule::class, - ] - ) - interface TestComponent { - - val underTest: NotificationsKeyguardViewStateRepositoryImpl - - val mockWakeUpCoordinator: NotificationWakeUpCoordinator - val testScope: TestScope - - @Component.Factory - interface Factory { - fun create( - @BindsInstance test: SysuiTestCase, - ): TestComponent - } - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt index 683d0aa33d4ae7b2e08e3c709a62ac644562e944..707026e4200976d3b71a3acf12b6a1635e595085 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationAlertsInteractorTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.domain.interactor import android.app.StatusBarManager import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule import com.android.systemui.SysuiTestCase import com.android.systemui.dagger.SysUISingleton @@ -31,8 +32,7 @@ class NotificationAlertsInteractorTest : SysuiTestCase() { @Component(modules = [SysUITestModule::class]) @SysUISingleton - interface TestComponent { - val underTest: NotificationAlertsInteractor + interface TestComponent : SysUITestComponent<NotificationAlertsInteractor> { val disableFlags: FakeDisableFlagsRepository @Component.Factory diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt index 705a5a3f9792fb4c9b7306739c1eeb48a898ed38..bb6f1b6a2850cf971ed973c2bf85bb6b23735f9c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/NotificationsKeyguardInteractorTest.kt @@ -14,7 +14,11 @@ package com.android.systemui.statusbar.notification.domain.interactor import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule +import com.android.collectLastValue +import com.android.runCurrent +import com.android.runTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dagger.SysUISingleton @@ -22,7 +26,6 @@ import com.android.systemui.statusbar.notification.data.repository.FakeNotificat import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test @@ -30,60 +33,48 @@ import org.junit.Test @SmallTest class NotificationsKeyguardInteractorTest : SysuiTestCase() { + @SysUISingleton + @Component(modules = [SysUITestModule::class]) + interface TestComponent : SysUITestComponent<NotificationsKeyguardInteractor> { + + val repository: FakeNotificationsKeyguardViewStateRepository + + @Component.Factory + interface Factory { + fun create(@BindsInstance test: SysuiTestCase): TestComponent + } + } + private val testComponent: TestComponent = DaggerNotificationsKeyguardInteractorTest_TestComponent.factory().create(test = this) @Test fun areNotifsFullyHidden_reflectsRepository() = - with(testComponent) { - testScope.runTest { - repository.setNotificationsFullyHidden(false) - val notifsFullyHidden by collectLastValue(underTest.areNotificationsFullyHidden) - runCurrent() + testComponent.runTest { + repository.setNotificationsFullyHidden(false) + val notifsFullyHidden by collectLastValue(underTest.areNotificationsFullyHidden) + runCurrent() - assertThat(notifsFullyHidden).isFalse() + assertThat(notifsFullyHidden).isFalse() - repository.setNotificationsFullyHidden(true) - runCurrent() + repository.setNotificationsFullyHidden(true) + runCurrent() - assertThat(notifsFullyHidden).isTrue() - } + assertThat(notifsFullyHidden).isTrue() } @Test fun isPulseExpanding_reflectsRepository() = - with(testComponent) { - testScope.runTest { - repository.setPulseExpanding(false) - val isPulseExpanding by collectLastValue(underTest.isPulseExpanding) - runCurrent() + testComponent.runTest { + repository.setPulseExpanding(false) + val isPulseExpanding by collectLastValue(underTest.isPulseExpanding) + runCurrent() - assertThat(isPulseExpanding).isFalse() + assertThat(isPulseExpanding).isFalse() - repository.setPulseExpanding(true) - runCurrent() + repository.setPulseExpanding(true) + runCurrent() - assertThat(isPulseExpanding).isTrue() - } + assertThat(isPulseExpanding).isTrue() } - - @SysUISingleton - @Component( - modules = - [ - SysUITestModule::class, - ] - ) - interface TestComponent { - - val underTest: NotificationsKeyguardInteractor - - val repository: FakeNotificationsKeyguardViewStateRepository - val testScope: TestScope - - @Component.Factory - interface Factory { - fun create(@BindsInstance test: SysuiTestCase): TestComponent - } - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt index f8252a721b32fe463e23a856800afc3726f3b13c..05deb1cc75c799f46053391257c2dfc29afc85e2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt @@ -17,10 +17,12 @@ package com.android.systemui.statusbar.notification.icon.domain.interactor import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule import com.android.TestMocksModule +import com.android.collectLastValue +import com.android.runTest import com.android.systemui.SysuiTestCase -import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dagger.SysUISingleton import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository import com.android.systemui.statusbar.data.repository.NotificationListenerSettingsRepository @@ -43,8 +45,6 @@ import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component import java.util.Optional -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -57,12 +57,10 @@ class NotificationIconsInteractorTest : SysuiTestCase() { @Component(modules = [SysUITestModule::class]) @SysUISingleton - interface TestComponent { - val underTest: NotificationIconsInteractor + interface TestComponent : SysUITestComponent<NotificationIconsInteractor> { val activeNotificationListRepository: ActiveNotificationListRepository val keyguardViewStateRepository: FakeNotificationsKeyguardViewStateRepository - val testScope: TestScope @Component.Factory interface Factory { @@ -75,97 +73,78 @@ class NotificationIconsInteractorTest : SysuiTestCase() { .create(test = this, mocks = TestMocksModule(bubbles = Optional.of(bubbles))) @Before - fun setup() = - with(testComponent) { + fun setup() { + testComponent.apply { activeNotificationListRepository.activeNotifications.value = ActiveNotificationsStore.Builder() .apply { testIcons.forEach(::addIndividualNotif) } .build() } + } @Test fun filteredEntrySet() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.filteredNotifSet()) - assertThat(filteredSet).containsExactlyElementsIn(testIcons) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.filteredNotifSet()) + assertThat(filteredSet).containsExactlyElementsIn(testIcons) } @Test fun filteredEntrySet_noExpandedBubbles() = - with(testComponent) { - testScope.runTest { - whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true) - val filteredSet by collectLastValue(underTest.filteredNotifSet()) - assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1") - } + testComponent.runTest { + whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true) + val filteredSet by collectLastValue(underTest.filteredNotifSet()) + assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1") } @Test fun filteredEntrySet_noAmbient() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.filteredNotifSet(showAmbient = false)) - assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true) - assertThat(filteredSet) - .comparingElementsUsing(byIsSuppressedFromStatusBar) - .doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.filteredNotifSet(showAmbient = false)) + assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true) + assertThat(filteredSet) + .comparingElementsUsing(byIsSuppressedFromStatusBar) + .doesNotContain(true) } @Test fun filteredEntrySet_noLowPriority() = - with(testComponent) { - testScope.runTest { - val filteredSet by - collectLastValue(underTest.filteredNotifSet(showLowPriority = false)) - assertThat(filteredSet).comparingElementsUsing(byIsSilent).doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.filteredNotifSet(showLowPriority = false)) + assertThat(filteredSet).comparingElementsUsing(byIsSilent).doesNotContain(true) } @Test fun filteredEntrySet_noDismissed() = - with(testComponent) { - testScope.runTest { - val filteredSet by - collectLastValue(underTest.filteredNotifSet(showDismissed = false)) - assertThat(filteredSet) - .comparingElementsUsing(byIsRowDismissed) - .doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.filteredNotifSet(showDismissed = false)) + assertThat(filteredSet).comparingElementsUsing(byIsRowDismissed).doesNotContain(true) } @Test fun filteredEntrySet_noRepliedMessages() = - with(testComponent) { - testScope.runTest { - val filteredSet by - collectLastValue(underTest.filteredNotifSet(showRepliedMessages = false)) - assertThat(filteredSet) - .comparingElementsUsing(byIsLastMessageFromReply) - .doesNotContain(true) - } + testComponent.runTest { + val filteredSet by + collectLastValue(underTest.filteredNotifSet(showRepliedMessages = false)) + assertThat(filteredSet) + .comparingElementsUsing(byIsLastMessageFromReply) + .doesNotContain(true) } @Test fun filteredEntrySet_noPulsing_notifsNotFullyHidden() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.filteredNotifSet(showPulsing = false)) - keyguardViewStateRepository.setNotificationsFullyHidden(false) - assertThat(filteredSet).comparingElementsUsing(byIsPulsing).doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.filteredNotifSet(showPulsing = false)) + keyguardViewStateRepository.setNotificationsFullyHidden(false) + assertThat(filteredSet).comparingElementsUsing(byIsPulsing).doesNotContain(true) } @Test fun filteredEntrySet_noPulsing_notifsFullyHidden() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.filteredNotifSet(showPulsing = false)) - keyguardViewStateRepository.setNotificationsFullyHidden(true) - assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.filteredNotifSet(showPulsing = false)) + keyguardViewStateRepository.setNotificationsFullyHidden(true) + assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true) } } @@ -177,13 +156,11 @@ class AlwaysOnDisplayNotificationIconsInteractorTest : SysuiTestCase() { @Component(modules = [SysUITestModule::class]) @SysUISingleton - interface TestComponent { - val underTest: AlwaysOnDisplayNotificationIconsInteractor + interface TestComponent : SysUITestComponent<AlwaysOnDisplayNotificationIconsInteractor> { val activeNotificationListRepository: ActiveNotificationListRepository val deviceEntryRepository: FakeDeviceEntryRepository val keyguardViewStateRepository: FakeNotificationsKeyguardViewStateRepository - val testScope: TestScope @Component.Factory interface Factory { @@ -191,105 +168,88 @@ class AlwaysOnDisplayNotificationIconsInteractorTest : SysuiTestCase() { } } - val testComponent: TestComponent = + private val testComponent: TestComponent = DaggerAlwaysOnDisplayNotificationIconsInteractorTest_TestComponent.factory() .create(test = this, mocks = TestMocksModule(bubbles = Optional.of(bubbles))) @Before - fun setup() = - with(testComponent) { + fun setup() { + testComponent.apply { activeNotificationListRepository.activeNotifications.value = ActiveNotificationsStore.Builder() .apply { testIcons.forEach(::addIndividualNotif) } .build() } + } @Test fun filteredEntrySet_noExpandedBubbles() = - with(testComponent) { - testScope.runTest { - whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true) - val filteredSet by collectLastValue(underTest.aodNotifs) - assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1") - } + testComponent.runTest { + whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true) + val filteredSet by collectLastValue(underTest.aodNotifs) + assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1") } @Test fun filteredEntrySet_noAmbient() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.aodNotifs) - assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true) - assertThat(filteredSet) - .comparingElementsUsing(byIsSuppressedFromStatusBar) - .doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.aodNotifs) + assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true) + assertThat(filteredSet) + .comparingElementsUsing(byIsSuppressedFromStatusBar) + .doesNotContain(true) } @Test fun filteredEntrySet_noDismissed() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.aodNotifs) - assertThat(filteredSet) - .comparingElementsUsing(byIsRowDismissed) - .doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.aodNotifs) + assertThat(filteredSet).comparingElementsUsing(byIsRowDismissed).doesNotContain(true) } @Test fun filteredEntrySet_noRepliedMessages() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.aodNotifs) - assertThat(filteredSet) - .comparingElementsUsing(byIsLastMessageFromReply) - .doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.aodNotifs) + assertThat(filteredSet) + .comparingElementsUsing(byIsLastMessageFromReply) + .doesNotContain(true) } @Test fun filteredEntrySet_showPulsing_notifsNotFullyHidden_bypassDisabled() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.aodNotifs) - deviceEntryRepository.setBypassEnabled(false) - keyguardViewStateRepository.setNotificationsFullyHidden(false) - assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.aodNotifs) + deviceEntryRepository.setBypassEnabled(false) + keyguardViewStateRepository.setNotificationsFullyHidden(false) + assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true) } @Test fun filteredEntrySet_showPulsing_notifsFullyHidden_bypassDisabled() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.aodNotifs) - deviceEntryRepository.setBypassEnabled(false) - keyguardViewStateRepository.setNotificationsFullyHidden(true) - assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.aodNotifs) + deviceEntryRepository.setBypassEnabled(false) + keyguardViewStateRepository.setNotificationsFullyHidden(true) + assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true) } @Test fun filteredEntrySet_noPulsing_notifsNotFullyHidden_bypassEnabled() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.aodNotifs) - deviceEntryRepository.setBypassEnabled(true) - keyguardViewStateRepository.setNotificationsFullyHidden(false) - assertThat(filteredSet).comparingElementsUsing(byIsPulsing).doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.aodNotifs) + deviceEntryRepository.setBypassEnabled(true) + keyguardViewStateRepository.setNotificationsFullyHidden(false) + assertThat(filteredSet).comparingElementsUsing(byIsPulsing).doesNotContain(true) } @Test fun filteredEntrySet_showPulsing_notifsFullyHidden_bypassEnabled() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.aodNotifs) - deviceEntryRepository.setBypassEnabled(true) - keyguardViewStateRepository.setNotificationsFullyHidden(true) - assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.aodNotifs) + deviceEntryRepository.setBypassEnabled(true) + keyguardViewStateRepository.setNotificationsFullyHidden(true) + assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true) } } @@ -301,13 +261,11 @@ class StatusBarNotificationIconsInteractorTest : SysuiTestCase() { @Component(modules = [SysUITestModule::class]) @SysUISingleton - interface TestComponent { - val underTest: StatusBarNotificationIconsInteractor + interface TestComponent : SysUITestComponent<StatusBarNotificationIconsInteractor> { val activeNotificationListRepository: ActiveNotificationListRepository val keyguardViewStateRepository: FakeNotificationsKeyguardViewStateRepository val notificationListenerSettingsRepository: NotificationListenerSettingsRepository - val testScope: TestScope @Component.Factory interface Factory { @@ -320,76 +278,63 @@ class StatusBarNotificationIconsInteractorTest : SysuiTestCase() { .create(test = this, mocks = TestMocksModule(bubbles = Optional.of(bubbles))) @Before - fun setup() = - with(testComponent) { + fun setup() { + testComponent.apply { activeNotificationListRepository.activeNotifications.value = ActiveNotificationsStore.Builder() .apply { testIcons.forEach(::addIndividualNotif) } .build() } + } @Test fun filteredEntrySet_noExpandedBubbles() = - with(testComponent) { - testScope.runTest { - whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true) - val filteredSet by collectLastValue(underTest.statusBarNotifs) - assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1") - } + testComponent.runTest { + whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true) + val filteredSet by collectLastValue(underTest.statusBarNotifs) + assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1") } @Test fun filteredEntrySet_noAmbient() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.statusBarNotifs) - assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true) - assertThat(filteredSet) - .comparingElementsUsing(byIsSuppressedFromStatusBar) - .doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.statusBarNotifs) + assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true) + assertThat(filteredSet) + .comparingElementsUsing(byIsSuppressedFromStatusBar) + .doesNotContain(true) } @Test fun filteredEntrySet_noLowPriority_whenDontShowSilentIcons() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.statusBarNotifs) - notificationListenerSettingsRepository.showSilentStatusIcons.value = false - assertThat(filteredSet).comparingElementsUsing(byIsSilent).doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.statusBarNotifs) + notificationListenerSettingsRepository.showSilentStatusIcons.value = false + assertThat(filteredSet).comparingElementsUsing(byIsSilent).doesNotContain(true) } @Test fun filteredEntrySet_showLowPriority_whenShowSilentIcons() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.statusBarNotifs) - notificationListenerSettingsRepository.showSilentStatusIcons.value = true - assertThat(filteredSet).comparingElementsUsing(byIsSilent).contains(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.statusBarNotifs) + notificationListenerSettingsRepository.showSilentStatusIcons.value = true + assertThat(filteredSet).comparingElementsUsing(byIsSilent).contains(true) } @Test fun filteredEntrySet_noDismissed() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.statusBarNotifs) - assertThat(filteredSet) - .comparingElementsUsing(byIsRowDismissed) - .doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.statusBarNotifs) + assertThat(filteredSet).comparingElementsUsing(byIsRowDismissed).doesNotContain(true) } @Test fun filteredEntrySet_noRepliedMessages() = - with(testComponent) { - testScope.runTest { - val filteredSet by collectLastValue(underTest.statusBarNotifs) - assertThat(filteredSet) - .comparingElementsUsing(byIsLastMessageFromReply) - .doesNotContain(true) - } + testComponent.runTest { + val filteredSet by collectLastValue(underTest.statusBarNotifs) + assertThat(filteredSet) + .comparingElementsUsing(byIsLastMessageFromReply) + .doesNotContain(true) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt index 49e1493f642f2ba095c76077b2abe65b5eb2e458..788cfbc47dd37e3498f1376aab31bbf924fc1f84 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt @@ -13,17 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@file:OptIn(ExperimentalCoroutinesApi::class) package com.android.systemui.statusbar.notification.icon.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule import com.android.TestMocksModule +import com.android.collectLastValue +import com.android.runCurrent +import com.android.runTest import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule -import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FakeFeatureFlagsClassicModule import com.android.systemui.flags.Flags @@ -41,6 +43,7 @@ import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.ScreenOffAnimationController import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository import com.android.systemui.user.domain.UserDomainLayerModule +import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.android.systemui.util.ui.isAnimating import com.android.systemui.util.ui.stopAnimating @@ -48,71 +51,78 @@ import com.android.systemui.util.ui.value import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mock -import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { - @Mock private lateinit var dozeParams: DozeParameters - @Mock private lateinit var screenOffAnimController: ScreenOffAnimationController + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + BiometricsDomainLayerModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent : + SysUITestComponent<NotificationIconContainerAlwaysOnDisplayViewModel> { - private lateinit var testComponent: TestComponent - private val underTest: NotificationIconContainerAlwaysOnDisplayViewModel - get() = testComponent.underTest - private val deviceProvisioningRepository: FakeDeviceProvisioningRepository - get() = testComponent.deviceProvisioningRepository - private val keyguardRepository: FakeKeyguardRepository - get() = testComponent.keyguardRepository - private val keyguardTransitionRepository: FakeKeyguardTransitionRepository - get() = testComponent.keyguardTransitionRepository - private val powerRepository: FakePowerRepository - get() = testComponent.powerRepository - private val scope: TestScope - get() = testComponent.scope + val deviceProvisioningRepository: FakeDeviceProvisioningRepository + val keyguardRepository: FakeKeyguardRepository + val keyguardTransitionRepository: FakeKeyguardTransitionRepository + val powerRepository: FakePowerRepository - @Before - fun setup() { - MockitoAnnotations.initMocks(this) + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + mocks: TestMocksModule, + featureFlags: FakeFeatureFlagsClassicModule, + ): TestComponent + } + } - testComponent = - DaggerNotificationIconContainerAlwaysOnDisplayViewModelTest_TestComponent.factory() - .create( - test = this, - featureFlags = - FakeFeatureFlagsClassicModule { - setDefault(Flags.FACE_AUTH_REFACTOR) - set(Flags.FULL_SCREEN_USER_SWITCHER, value = false) - setDefault(Flags.NEW_AOD_TRANSITION) - }, - mocks = - TestMocksModule( - dozeParameters = dozeParams, - screenOffAnimationController = screenOffAnimController, - ), - ) + private val dozeParams: DozeParameters = mock() + private val screenOffAnimController: ScreenOffAnimationController = mock() + + private val testComponent: TestComponent = + DaggerNotificationIconContainerAlwaysOnDisplayViewModelTest_TestComponent.factory() + .create( + test = this, + featureFlags = + FakeFeatureFlagsClassicModule { + setDefault(Flags.FACE_AUTH_REFACTOR) + set(Flags.FULL_SCREEN_USER_SWITCHER, value = false) + setDefault(Flags.NEW_AOD_TRANSITION) + }, + mocks = + TestMocksModule( + dozeParameters = dozeParams, + screenOffAnimationController = screenOffAnimController, + ), + ) - keyguardRepository.setKeyguardShowing(true) - keyguardRepository.setKeyguardOccluded(false) - deviceProvisioningRepository.setFactoryResetProtectionActive(false) - powerRepository.updateWakefulness( - rawState = WakefulnessState.AWAKE, - lastWakeReason = WakeSleepReason.OTHER, - lastSleepReason = WakeSleepReason.OTHER, - ) + @Before + fun setup() { + testComponent.apply { + keyguardRepository.setKeyguardShowing(true) + keyguardRepository.setKeyguardOccluded(false) + deviceProvisioningRepository.setFactoryResetProtectionActive(false) + powerRepository.updateWakefulness( + rawState = WakefulnessState.AWAKE, + lastWakeReason = WakeSleepReason.OTHER, + lastSleepReason = WakeSleepReason.OTHER, + ) + } } @Test fun animationsEnabled_isFalse_whenFrpIsActive() = - scope.runTest { + testComponent.runTest { deviceProvisioningRepository.setFactoryResetProtectionActive(true) keyguardTransitionRepository.sendTransitionStep( TransitionStep( @@ -126,7 +136,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun animationsEnabled_isFalse_whenDeviceAsleepAndNotPulsing() = - scope.runTest { + testComponent.runTest { powerRepository.updateWakefulness( rawState = WakefulnessState.ASLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -149,7 +159,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun animationsEnabled_isTrue_whenDeviceAsleepAndPulsing() = - scope.runTest { + testComponent.runTest { powerRepository.updateWakefulness( rawState = WakefulnessState.ASLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -172,7 +182,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun animationsEnabled_isFalse_whenStartingToSleepAndNotControlScreenOff() = - scope.runTest { + testComponent.runTest { powerRepository.updateWakefulness( rawState = WakefulnessState.STARTING_TO_SLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -193,7 +203,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() = - scope.runTest { + testComponent.runTest { powerRepository.updateWakefulness( rawState = WakefulnessState.STARTING_TO_SLEEP, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -214,7 +224,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun animationsEnabled_isTrue_whenNotAsleep() = - scope.runTest { + testComponent.runTest { powerRepository.updateWakefulness( rawState = WakefulnessState.AWAKE, lastWakeReason = WakeSleepReason.POWER_BUTTON, @@ -232,7 +242,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun animationsEnabled_isTrue_whenKeyguardIsShowing() = - scope.runTest { + testComponent.runTest { keyguardTransitionRepository.sendTransitionStep( TransitionStep( transitionState = TransitionState.STARTED, @@ -261,7 +271,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun isDozing_startAodTransition() = - scope.runTest { + testComponent.runTest { val isDozing by collectLastValue(underTest.isDozing) runCurrent() keyguardTransitionRepository.sendTransitionStep( @@ -278,7 +288,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun isDozing_startDozeTransition() = - scope.runTest { + testComponent.runTest { val isDozing by collectLastValue(underTest.isDozing) runCurrent() keyguardTransitionRepository.sendTransitionStep( @@ -295,7 +305,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun isDozing_startDozeToAodTransition() = - scope.runTest { + testComponent.runTest { val isDozing by collectLastValue(underTest.isDozing) runCurrent() keyguardTransitionRepository.sendTransitionStep( @@ -312,7 +322,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun isNotDozing_startAodToGoneTransition() = - scope.runTest { + testComponent.runTest { val isDozing by collectLastValue(underTest.isDozing) runCurrent() keyguardTransitionRepository.sendTransitionStep( @@ -329,7 +339,7 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { @Test fun isDozing_stopAnimation() = - scope.runTest { + testComponent.runTest { val isDozing by collectLastValue(underTest.isDozing) runCurrent() keyguardTransitionRepository.sendTransitionStep( @@ -347,33 +357,4 @@ class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() { assertThat(isDozing?.isAnimating).isEqualTo(false) } - - @SysUISingleton - @Component( - modules = - [ - SysUITestModule::class, - BiometricsDomainLayerModule::class, - UserDomainLayerModule::class, - ] - ) - interface TestComponent { - - val underTest: NotificationIconContainerAlwaysOnDisplayViewModel - - val deviceProvisioningRepository: FakeDeviceProvisioningRepository - val keyguardRepository: FakeKeyguardRepository - val keyguardTransitionRepository: FakeKeyguardTransitionRepository - val powerRepository: FakePowerRepository - val scope: TestScope - - @Component.Factory - interface Factory { - fun create( - @BindsInstance test: SysuiTestCase, - mocks: TestMocksModule, - featureFlags: FakeFeatureFlagsClassicModule, - ): TestComponent - } - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt index 44acac8620ee69298bc4044b8da83a3733466a82..1a04a3ea291a592d7412ce4cb93d2a117c893f8a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@file:OptIn(ExperimentalCoroutinesApi::class) package com.android.systemui.statusbar.notification.icon.ui.viewmodel @@ -21,11 +20,14 @@ import android.graphics.Rect import android.graphics.drawable.Icon import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule import com.android.TestMocksModule +import com.android.collectLastValue +import com.android.runCurrent +import com.android.runTest import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule -import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FakeFeatureFlagsClassicModule import com.android.systemui.flags.Flags @@ -57,373 +59,334 @@ import com.android.systemui.util.ui.value import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mock -import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) class NotificationIconContainerStatusBarViewModelTest : SysuiTestCase() { - @Mock lateinit var dozeParams: DozeParameters + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + BiometricsDomainLayerModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent : SysUITestComponent<NotificationIconContainerStatusBarViewModel> { - private lateinit var testComponent: TestComponent + val activeNotificationsRepository: ActiveNotificationListRepository + val darkIconRepository: FakeDarkIconRepository + val deviceProvisioningRepository: FakeDeviceProvisioningRepository + val headsUpViewStateRepository: HeadsUpNotificationIconViewStateRepository + val keyguardTransitionRepository: FakeKeyguardTransitionRepository + val keyguardRepository: FakeKeyguardRepository + val powerRepository: FakePowerRepository + val shadeRepository: FakeShadeRepository + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + mocks: TestMocksModule, + featureFlags: FakeFeatureFlagsClassicModule, + ): TestComponent + } + } + + private val dozeParams: DozeParameters = mock() + + private val testComponent: TestComponent = + DaggerNotificationIconContainerStatusBarViewModelTest_TestComponent.factory() + .create( + test = this, + featureFlags = + FakeFeatureFlagsClassicModule { + setDefault(Flags.FACE_AUTH_REFACTOR) + set(Flags.FULL_SCREEN_USER_SWITCHER, value = false) + }, + mocks = + TestMocksModule( + dozeParameters = dozeParams, + ), + ) @Before fun setup() { - MockitoAnnotations.initMocks(this) - - testComponent = - DaggerNotificationIconContainerStatusBarViewModelTest_TestComponent.factory() - .create( - test = this, - featureFlags = - FakeFeatureFlagsClassicModule { - set(Flags.FACE_AUTH_REFACTOR, value = false) - set(Flags.FULL_SCREEN_USER_SWITCHER, value = false) - }, - mocks = - TestMocksModule( - dozeParameters = dozeParams, - ), - ) - .apply { - keyguardRepository.setKeyguardShowing(false) - deviceProvisioningRepository.setFactoryResetProtectionActive(false) - powerRepository.updateWakefulness( - rawState = WakefulnessState.AWAKE, - lastWakeReason = WakeSleepReason.OTHER, - lastSleepReason = WakeSleepReason.OTHER, - ) - } + testComponent.apply { + keyguardRepository.setKeyguardShowing(false) + deviceProvisioningRepository.setFactoryResetProtectionActive(false) + powerRepository.updateWakefulness( + rawState = WakefulnessState.AWAKE, + lastWakeReason = WakeSleepReason.OTHER, + lastSleepReason = WakeSleepReason.OTHER, + ) + } } @Test fun animationsEnabled_isFalse_whenFrpIsActive() = - with(testComponent) { - scope.runTest { - deviceProvisioningRepository.setFactoryResetProtectionActive(true) - keyguardTransitionRepository.sendTransitionStep( - TransitionStep( - transitionState = TransitionState.STARTED, - ) + testComponent.runTest { + deviceProvisioningRepository.setFactoryResetProtectionActive(true) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, ) - val animationsEnabled by collectLastValue(underTest.animationsEnabled) - runCurrent() - assertThat(animationsEnabled).isFalse() - } + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isFalse() } @Test fun animationsEnabled_isFalse_whenDeviceAsleepAndNotPulsing() = - with(testComponent) { - scope.runTest { - powerRepository.updateWakefulness( - rawState = WakefulnessState.ASLEEP, - lastWakeReason = WakeSleepReason.POWER_BUTTON, - lastSleepReason = WakeSleepReason.OTHER, - ) - keyguardTransitionRepository.sendTransitionStep( - TransitionStep( - transitionState = TransitionState.STARTED, - ) + testComponent.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.ASLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, ) - keyguardRepository.setDozeTransitionModel( - DozeTransitionModel( - to = DozeStateModel.DOZE_AOD, - ) + ) + keyguardRepository.setDozeTransitionModel( + DozeTransitionModel( + to = DozeStateModel.DOZE_AOD, ) - val animationsEnabled by collectLastValue(underTest.animationsEnabled) - runCurrent() - assertThat(animationsEnabled).isFalse() - } + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isFalse() } @Test fun animationsEnabled_isTrue_whenDeviceAsleepAndPulsing() = - with(testComponent) { - scope.runTest { - powerRepository.updateWakefulness( - rawState = WakefulnessState.ASLEEP, - lastWakeReason = WakeSleepReason.POWER_BUTTON, - lastSleepReason = WakeSleepReason.OTHER, + testComponent.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.ASLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, ) - keyguardTransitionRepository.sendTransitionStep( - TransitionStep( - transitionState = TransitionState.STARTED, - ) + ) + keyguardRepository.setDozeTransitionModel( + DozeTransitionModel( + to = DozeStateModel.DOZE_PULSING, ) - keyguardRepository.setDozeTransitionModel( - DozeTransitionModel( - to = DozeStateModel.DOZE_PULSING, - ) - ) - val animationsEnabled by collectLastValue(underTest.animationsEnabled) - runCurrent() - assertThat(animationsEnabled).isTrue() - } + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isTrue() } @Test fun animationsEnabled_isFalse_whenStartingToSleepAndNotControlScreenOff() = - with(testComponent) { - scope.runTest { - powerRepository.updateWakefulness( - rawState = WakefulnessState.STARTING_TO_SLEEP, - lastWakeReason = WakeSleepReason.POWER_BUTTON, - lastSleepReason = WakeSleepReason.OTHER, - ) - keyguardTransitionRepository.sendTransitionStep( - TransitionStep( - from = KeyguardState.GONE, - to = KeyguardState.AOD, - transitionState = TransitionState.STARTED, - ) + testComponent.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.AOD, + transitionState = TransitionState.STARTED, ) - whenever(dozeParams.shouldControlScreenOff()).thenReturn(false) - val animationsEnabled by collectLastValue(underTest.animationsEnabled) - runCurrent() - assertThat(animationsEnabled).isFalse() - } + ) + whenever(dozeParams.shouldControlScreenOff()).thenReturn(false) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isFalse() } @Test fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() = - with(testComponent) { - scope.runTest { - powerRepository.updateWakefulness( - rawState = WakefulnessState.STARTING_TO_SLEEP, - lastWakeReason = WakeSleepReason.POWER_BUTTON, - lastSleepReason = WakeSleepReason.OTHER, + testComponent.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.STARTING_TO_SLEEP, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.GONE, + to = KeyguardState.AOD, + transitionState = TransitionState.STARTED, ) - keyguardTransitionRepository.sendTransitionStep( - TransitionStep( - from = KeyguardState.GONE, - to = KeyguardState.AOD, - transitionState = TransitionState.STARTED, - ) - ) - whenever(dozeParams.shouldControlScreenOff()).thenReturn(true) - val animationsEnabled by collectLastValue(underTest.animationsEnabled) - runCurrent() - assertThat(animationsEnabled).isTrue() - } + ) + whenever(dozeParams.shouldControlScreenOff()).thenReturn(true) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isTrue() } @Test fun animationsEnabled_isTrue_whenNotAsleep() = - with(testComponent) { - scope.runTest { - powerRepository.updateWakefulness( - rawState = WakefulnessState.AWAKE, - lastWakeReason = WakeSleepReason.POWER_BUTTON, - lastSleepReason = WakeSleepReason.OTHER, - ) - keyguardTransitionRepository.sendTransitionStep( - TransitionStep( - transitionState = TransitionState.STARTED, - ) + testComponent.runTest { + powerRepository.updateWakefulness( + rawState = WakefulnessState.AWAKE, + lastWakeReason = WakeSleepReason.POWER_BUTTON, + lastSleepReason = WakeSleepReason.OTHER, + ) + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, ) - val animationsEnabled by collectLastValue(underTest.animationsEnabled) - runCurrent() - assertThat(animationsEnabled).isTrue() - } + ) + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + runCurrent() + assertThat(animationsEnabled).isTrue() } @Test fun animationsEnabled_isTrue_whenKeyguardIsNotShowing() = - with(testComponent) { - scope.runTest { - val animationsEnabled by collectLastValue(underTest.animationsEnabled) - - keyguardTransitionRepository.sendTransitionStep( - TransitionStep( - transitionState = TransitionState.STARTED, - ) + testComponent.runTest { + val animationsEnabled by collectLastValue(underTest.animationsEnabled) + + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, ) - keyguardRepository.setKeyguardShowing(true) - runCurrent() + ) + keyguardRepository.setKeyguardShowing(true) + runCurrent() - assertThat(animationsEnabled).isFalse() + assertThat(animationsEnabled).isFalse() - keyguardRepository.setKeyguardShowing(false) - runCurrent() + keyguardRepository.setKeyguardShowing(false) + runCurrent() - assertThat(animationsEnabled).isTrue() - } + assertThat(animationsEnabled).isTrue() } @Test fun iconColors_testsDarkBounds() = - with(testComponent) { - scope.runTest { - darkIconRepository.darkState.value = - SysuiDarkIconDispatcher.DarkChange( - emptyList(), - 0f, - 0xAABBCC, - ) - val iconColorsLookup by collectLastValue(underTest.iconColors) - assertThat(iconColorsLookup).isNotNull() - - val iconColors = iconColorsLookup?.iconColors(Rect()) - assertThat(iconColors).isNotNull() - iconColors!! - - assertThat(iconColors.tint).isEqualTo(0xAABBCC) - - val staticDrawableColor = iconColors.staticDrawableColor(Rect(), isColorized = true) - - assertThat(staticDrawableColor).isEqualTo(0xAABBCC) - } + testComponent.runTest { + darkIconRepository.darkState.value = + SysuiDarkIconDispatcher.DarkChange( + emptyList(), + 0f, + 0xAABBCC, + ) + val iconColorsLookup by collectLastValue(underTest.iconColors) + assertThat(iconColorsLookup).isNotNull() + + val iconColors = iconColorsLookup?.iconColors(Rect()) + assertThat(iconColors).isNotNull() + iconColors!! + + assertThat(iconColors.tint).isEqualTo(0xAABBCC) + + val staticDrawableColor = iconColors.staticDrawableColor(Rect(), isColorized = true) + + assertThat(staticDrawableColor).isEqualTo(0xAABBCC) } @Test fun iconColors_staticDrawableColor_nonColorized() = - with(testComponent) { - scope.runTest { - darkIconRepository.darkState.value = - SysuiDarkIconDispatcher.DarkChange( - emptyList(), - 0f, - 0xAABBCC, - ) - val iconColorsLookup by collectLastValue(underTest.iconColors) - val iconColors = iconColorsLookup?.iconColors(Rect()) - val staticDrawableColor = - iconColors?.staticDrawableColor(Rect(), isColorized = false) - assertThat(staticDrawableColor).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT) - } + testComponent.runTest { + darkIconRepository.darkState.value = + SysuiDarkIconDispatcher.DarkChange( + emptyList(), + 0f, + 0xAABBCC, + ) + val iconColorsLookup by collectLastValue(underTest.iconColors) + val iconColors = iconColorsLookup?.iconColors(Rect()) + val staticDrawableColor = iconColors?.staticDrawableColor(Rect(), isColorized = false) + assertThat(staticDrawableColor).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT) } @Test fun iconColors_staticDrawableColor_isColorized_notInDarkTintArea() = - with(testComponent) { - scope.runTest { - darkIconRepository.darkState.value = - SysuiDarkIconDispatcher.DarkChange( - listOf(Rect(0, 0, 5, 5)), - 0f, - 0xAABBCC, - ) - val iconColorsLookup by collectLastValue(underTest.iconColors) - val iconColors = iconColorsLookup?.iconColors(Rect(1, 1, 4, 4)) - val staticDrawableColor = - iconColors?.staticDrawableColor(Rect(6, 6, 7, 7), isColorized = true) - assertThat(staticDrawableColor).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT) - } + testComponent.runTest { + darkIconRepository.darkState.value = + SysuiDarkIconDispatcher.DarkChange( + listOf(Rect(0, 0, 5, 5)), + 0f, + 0xAABBCC, + ) + val iconColorsLookup by collectLastValue(underTest.iconColors) + val iconColors = iconColorsLookup?.iconColors(Rect(1, 1, 4, 4)) + val staticDrawableColor = + iconColors?.staticDrawableColor(Rect(6, 6, 7, 7), isColorized = true) + assertThat(staticDrawableColor).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT) } @Test fun iconColors_notInDarkTintArea() = - with(testComponent) { - scope.runTest { - darkIconRepository.darkState.value = - SysuiDarkIconDispatcher.DarkChange( - listOf(Rect(0, 0, 5, 5)), - 0f, - 0xAABBCC, - ) - val iconColorsLookup by collectLastValue(underTest.iconColors) - val iconColors = iconColorsLookup?.iconColors(Rect(6, 6, 7, 7)) - assertThat(iconColors).isNull() - } + testComponent.runTest { + darkIconRepository.darkState.value = + SysuiDarkIconDispatcher.DarkChange( + listOf(Rect(0, 0, 5, 5)), + 0f, + 0xAABBCC, + ) + val iconColorsLookup by collectLastValue(underTest.iconColors) + val iconColors = iconColorsLookup?.iconColors(Rect(6, 6, 7, 7)) + assertThat(iconColors).isNull() } @Test fun isolatedIcon_animateOnAppear_shadeCollapsed() = - with(testComponent) { - scope.runTest { - val icon: Icon = mock() - shadeRepository.setLegacyShadeExpansion(0f) - activeNotificationsRepository.activeNotifications.value = - ActiveNotificationsStore.Builder() - .apply { - addIndividualNotif( - activeNotificationModel( - key = "notif1", - groupKey = "group", - statusBarIcon = icon - ) + testComponent.runTest { + val icon: Icon = mock() + shadeRepository.setLegacyShadeExpansion(0f) + activeNotificationsRepository.activeNotifications.value = + ActiveNotificationsStore.Builder() + .apply { + addIndividualNotif( + activeNotificationModel( + key = "notif1", + groupKey = "group", + statusBarIcon = icon ) - } - .build() - val isolatedIcon by collectLastValue(underTest.isolatedIcon) - runCurrent() + ) + } + .build() + val isolatedIcon by collectLastValue(underTest.isolatedIcon) + runCurrent() - headsUpViewStateRepository.isolatedNotification.value = "notif1" - runCurrent() + headsUpViewStateRepository.isolatedNotification.value = "notif1" + runCurrent() - assertThat(isolatedIcon?.value?.notifKey).isEqualTo("notif1") - assertThat(isolatedIcon?.isAnimating).isTrue() - } + assertThat(isolatedIcon?.value?.notifKey).isEqualTo("notif1") + assertThat(isolatedIcon?.isAnimating).isTrue() } @Test fun isolatedIcon_dontAnimateOnAppear_shadeExpanded() = - with(testComponent) { - scope.runTest { - val icon: Icon = mock() - shadeRepository.setLegacyShadeExpansion(.5f) - activeNotificationsRepository.activeNotifications.value = - ActiveNotificationsStore.Builder() - .apply { - addIndividualNotif( - activeNotificationModel( - key = "notif1", - groupKey = "group", - statusBarIcon = icon - ) + testComponent.runTest { + val icon: Icon = mock() + shadeRepository.setLegacyShadeExpansion(.5f) + activeNotificationsRepository.activeNotifications.value = + ActiveNotificationsStore.Builder() + .apply { + addIndividualNotif( + activeNotificationModel( + key = "notif1", + groupKey = "group", + statusBarIcon = icon ) - } - .build() - val isolatedIcon by collectLastValue(underTest.isolatedIcon) - runCurrent() + ) + } + .build() + val isolatedIcon by collectLastValue(underTest.isolatedIcon) + runCurrent() - headsUpViewStateRepository.isolatedNotification.value = "notif1" - runCurrent() + headsUpViewStateRepository.isolatedNotification.value = "notif1" + runCurrent() - assertThat(isolatedIcon?.value?.notifKey).isEqualTo("notif1") - assertThat(isolatedIcon?.isAnimating).isFalse() - } + assertThat(isolatedIcon?.value?.notifKey).isEqualTo("notif1") + assertThat(isolatedIcon?.isAnimating).isFalse() } - - @SysUISingleton - @Component( - modules = - [ - SysUITestModule::class, - BiometricsDomainLayerModule::class, - UserDomainLayerModule::class, - ] - ) - interface TestComponent { - - val underTest: NotificationIconContainerStatusBarViewModel - - val activeNotificationsRepository: ActiveNotificationListRepository - val darkIconRepository: FakeDarkIconRepository - val deviceProvisioningRepository: FakeDeviceProvisioningRepository - val headsUpViewStateRepository: HeadsUpNotificationIconViewStateRepository - val keyguardTransitionRepository: FakeKeyguardTransitionRepository - val keyguardRepository: FakeKeyguardRepository - val powerRepository: FakePowerRepository - val shadeRepository: FakeShadeRepository - val scope: TestScope - - @Component.Factory - interface Factory { - fun create( - @BindsInstance test: SysuiTestCase, - mocks: TestMocksModule, - featureFlags: FakeFeatureFlagsClassicModule, - ): TestComponent - } - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt index 02a67d04ce8f1abcd29ffb622cb689c5ec187801..7423c2decaecb8dec880207f791982eda640a817 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/shelf/ui/viewmodel/NotificationShelfViewModelTest.kt @@ -14,17 +14,17 @@ * limitations under the License. */ -@file:OptIn(ExperimentalCoroutinesApi::class) - package com.android.systemui.statusbar.notification.shelf.ui.viewmodel import android.os.PowerManager import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule import com.android.TestMocksModule +import com.android.collectLastValue +import com.android.runTest import com.android.systemui.SysuiTestCase -import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository @@ -34,111 +34,105 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.row.ui.viewmodel.ActivatableNotificationViewModelModule import com.android.systemui.statusbar.phone.ScreenOffAnimationController import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runTest -import org.junit.Before -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.verify -import org.mockito.junit.MockitoJUnit -import org.mockito.junit.MockitoRule @RunWith(AndroidTestingRunner::class) @SmallTest class NotificationShelfViewModelTest : SysuiTestCase() { - @Rule @JvmField val mockitoRule: MockitoRule = MockitoJUnit.rule() - - @Mock private lateinit var keyguardTransitionController: LockscreenShadeTransitionController - @Mock private lateinit var screenOffAnimationController: ScreenOffAnimationController - @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController - - private lateinit var testComponent: TestComponent - - @Before - fun setUp() { - whenever(screenOffAnimationController.allowWakeUpIfDozing()).thenReturn(true) - testComponent = - DaggerNotificationShelfViewModelTest_TestComponent.factory() - .create( - test = this, - mocks = - TestMocksModule( - lockscreenShadeTransitionController = keyguardTransitionController, - screenOffAnimationController = screenOffAnimationController, - statusBarStateController = statusBarStateController, - ) - ) + @Component(modules = [SysUITestModule::class, ActivatableNotificationViewModelModule::class]) + @SysUISingleton + interface TestComponent : SysUITestComponent<NotificationShelfViewModel> { + + val deviceEntryFaceAuthRepository: FakeDeviceEntryFaceAuthRepository + val keyguardRepository: FakeKeyguardRepository + val powerRepository: FakePowerRepository + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + mocks: TestMocksModule, + ): TestComponent + } } + private val keyguardTransitionController: LockscreenShadeTransitionController = mock() + private val screenOffAnimationController: ScreenOffAnimationController = mock { + whenever(allowWakeUpIfDozing()).thenReturn(true) + } + private val statusBarStateController: SysuiStatusBarStateController = mock() + + private val testComponent: TestComponent = + DaggerNotificationShelfViewModelTest_TestComponent.factory() + .create( + test = this, + mocks = + TestMocksModule( + lockscreenShadeTransitionController = keyguardTransitionController, + screenOffAnimationController = screenOffAnimationController, + statusBarStateController = statusBarStateController, + ) + ) + @Test fun canModifyColorOfNotifications_whenKeyguardNotShowing() = - with(testComponent) { - testScope.runTest { - val canModifyNotifColor by collectLastValue(underTest.canModifyColorOfNotifications) + testComponent.runTest { + val canModifyNotifColor by collectLastValue(underTest.canModifyColorOfNotifications) - keyguardRepository.setKeyguardShowing(false) + keyguardRepository.setKeyguardShowing(false) - assertThat(canModifyNotifColor).isTrue() - } + assertThat(canModifyNotifColor).isTrue() } @Test fun canModifyColorOfNotifications_whenKeyguardShowingAndNotBypass() = - with(testComponent) { - testScope.runTest { - val canModifyNotifColor by collectLastValue(underTest.canModifyColorOfNotifications) + testComponent.runTest { + val canModifyNotifColor by collectLastValue(underTest.canModifyColorOfNotifications) - keyguardRepository.setKeyguardShowing(true) - deviceEntryFaceAuthRepository.isBypassEnabled.value = false + keyguardRepository.setKeyguardShowing(true) + deviceEntryFaceAuthRepository.isBypassEnabled.value = false - assertThat(canModifyNotifColor).isTrue() - } + assertThat(canModifyNotifColor).isTrue() } @Test fun cannotModifyColorOfNotifications_whenBypass() = - with(testComponent) { - testScope.runTest { - val canModifyNotifColor by collectLastValue(underTest.canModifyColorOfNotifications) + testComponent.runTest { + val canModifyNotifColor by collectLastValue(underTest.canModifyColorOfNotifications) - keyguardRepository.setKeyguardShowing(true) - deviceEntryFaceAuthRepository.isBypassEnabled.value = true + keyguardRepository.setKeyguardShowing(true) + deviceEntryFaceAuthRepository.isBypassEnabled.value = true - assertThat(canModifyNotifColor).isFalse() - } + assertThat(canModifyNotifColor).isFalse() } @Test fun isClickable_whenKeyguardShowing() = - with(testComponent) { - testScope.runTest { - val isClickable by collectLastValue(underTest.isClickable) + testComponent.runTest { + val isClickable by collectLastValue(underTest.isClickable) - keyguardRepository.setKeyguardShowing(true) + keyguardRepository.setKeyguardShowing(true) - assertThat(isClickable).isTrue() - } + assertThat(isClickable).isTrue() } @Test fun isNotClickable_whenKeyguardNotShowing() = - with(testComponent) { - testScope.runTest { - val isClickable by collectLastValue(underTest.isClickable) + testComponent.runTest { + val isClickable by collectLastValue(underTest.isClickable) - keyguardRepository.setKeyguardShowing(false) + keyguardRepository.setKeyguardShowing(false) - assertThat(isClickable).isFalse() - } + assertThat(isClickable).isFalse() } @Test @@ -152,23 +146,4 @@ class NotificationShelfViewModelTest : SysuiTestCase() { assertThat(powerRepository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_GESTURE) verify(keyguardTransitionController).goToLockedShade(Mockito.isNull(), eq(true)) } - - @Component(modules = [SysUITestModule::class, ActivatableNotificationViewModelModule::class]) - @SysUISingleton - interface TestComponent { - - val underTest: NotificationShelfViewModel - val deviceEntryFaceAuthRepository: FakeDeviceEntryFaceAuthRepository - val keyguardRepository: FakeKeyguardRepository - val powerRepository: FakePowerRepository - val testScope: TestScope - - @Component.Factory - interface Factory { - fun create( - @BindsInstance test: SysuiTestCase, - mocks: TestMocksModule, - ): TestComponent - } - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt index 3a9d111bacf7b0707bc7b1a299dc7b6f7e526972..22553dfc4cb1b57c4602246bd6564e30da70f776 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt @@ -19,12 +19,15 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.SysUITestComponent import com.android.SysUITestModule import com.android.TestMocksModule +import com.android.collectLastValue +import com.android.runCurrent +import com.android.runTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.SharedNotificationContainerPosition import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository -import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FakeFeatureFlagsClassicModule import com.android.systemui.flags.Flags @@ -47,70 +50,64 @@ import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest -import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mock -import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) class SharedNotificationContainerViewModelTest : SysuiTestCase() { - private lateinit var testComponent: TestComponent - - private val shadeRepository - get() = testComponent.shadeRepository - private val keyguardRepository - get() = testComponent.keyguardRepository - private val configurationRepository - get() = testComponent.configurationRepository - private val sharedNotificationContainerInteractor: SharedNotificationContainerInteractor - get() = testComponent.sharedNotificationContainerInteractor - private val underTest: SharedNotificationContainerViewModel - get() = testComponent.underTest - private val keyguardInteractor: KeyguardInteractor - get() = testComponent.keyguardInteractor - private val keyguardTransitionRepository - get() = testComponent.keyguardTransitionRepository - private val testScope - get() = testComponent.testScope - - @Mock private lateinit var notificationStackSizeCalculator: NotificationStackSizeCalculator - @Mock - private lateinit var notificationStackScrollLayoutController: - NotificationStackScrollLayoutController - - @Before - fun setUp() { - MockitoAnnotations.initMocks(this) - - whenever(notificationStackScrollLayoutController.getView()).thenReturn(mock()) - whenever(notificationStackScrollLayoutController.getShelfHeight()).thenReturn(0) - - testComponent = - DaggerSharedNotificationContainerViewModelTest_TestComponent.factory() - .create( - test = this, - featureFlags = - FakeFeatureFlagsClassicModule { - set(Flags.FULL_SCREEN_USER_SWITCHER, true) - }, - mocks = - TestMocksModule( - notificationStackSizeCalculator = notificationStackSizeCalculator, - notificationStackScrollLayoutController = - notificationStackScrollLayoutController, - ) - ) + @SysUISingleton + @Component( + modules = + [ + SysUITestModule::class, + UserDomainLayerModule::class, + ] + ) + interface TestComponent : SysUITestComponent<SharedNotificationContainerViewModel> { + + val configurationRepository: FakeConfigurationRepository + val keyguardRepository: FakeKeyguardRepository + val keyguardInteractor: KeyguardInteractor + val keyguardTransitionRepository: FakeKeyguardTransitionRepository + val shadeRepository: FakeShadeRepository + val sharedNotificationContainerInteractor: SharedNotificationContainerInteractor + + @Component.Factory + interface Factory { + fun create( + @BindsInstance test: SysuiTestCase, + featureFlags: FakeFeatureFlagsClassicModule, + mocks: TestMocksModule, + ): TestComponent + } } + private val notificationStackSizeCalculator: NotificationStackSizeCalculator = mock() + private val notificationStackScrollLayoutController: NotificationStackScrollLayoutController = + mock { + whenever(view).thenReturn(mock()) + whenever(shelfHeight).thenReturn(0) + } + + private val testComponent: TestComponent = + DaggerSharedNotificationContainerViewModelTest_TestComponent.factory() + .create( + test = this, + featureFlags = + FakeFeatureFlagsClassicModule { set(Flags.FULL_SCREEN_USER_SWITCHER, true) }, + mocks = + TestMocksModule( + notificationStackSizeCalculator = notificationStackSizeCalculator, + notificationStackScrollLayoutController = + notificationStackScrollLayoutController, + ) + ) + @Test fun validateMarginStartInSplitShade() = - testScope.runTest { + testComponent.runTest { overrideResource(R.bool.config_use_split_notification_shade, true) overrideResource(R.dimen.notification_panel_margin_horizontal, 20) @@ -123,7 +120,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun validateMarginStart() = - testScope.runTest { + testComponent.runTest { overrideResource(R.bool.config_use_split_notification_shade, false) overrideResource(R.dimen.notification_panel_margin_horizontal, 20) @@ -136,7 +133,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun validateMarginEnd() = - testScope.runTest { + testComponent.runTest { overrideResource(R.dimen.notification_panel_margin_horizontal, 50) val dimens by collectLastValue(underTest.configurationBasedDimensions) @@ -148,7 +145,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun validateMarginBottom() = - testScope.runTest { + testComponent.runTest { overrideResource(R.dimen.notification_panel_margin_bottom, 50) val dimens by collectLastValue(underTest.configurationBasedDimensions) @@ -160,7 +157,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun validateMarginTopWithLargeScreenHeader() = - testScope.runTest { + testComponent.runTest { overrideResource(R.bool.config_use_large_screen_shade_header, true) overrideResource(R.dimen.large_screen_shade_header_height, 50) overrideResource(R.dimen.notification_panel_margin_top, 0) @@ -174,7 +171,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun validateMarginTop() = - testScope.runTest { + testComponent.runTest { overrideResource(R.bool.config_use_large_screen_shade_header, false) overrideResource(R.dimen.large_screen_shade_header_height, 50) overrideResource(R.dimen.notification_panel_margin_top, 0) @@ -188,7 +185,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun isOnLockscreen() = - testScope.runTest { + testComponent.runTest { val isOnLockscreen by collectLastValue(underTest.isOnLockscreen) keyguardTransitionRepository.sendTransitionSteps( @@ -212,7 +209,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { keyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.GONE, to = KeyguardState.LOCKSCREEN, - this, + testScope, ) assertThat(isOnLockscreen).isTrue() @@ -226,7 +223,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun isOnLockscreenWithoutShade() = - testScope.runTest { + testComponent.runTest { val isOnLockscreenWithoutShade by collectLastValue(underTest.isOnLockscreenWithoutShade) // First on AOD @@ -262,7 +259,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun positionOnLockscreenNotInSplitShade() = - testScope.runTest { + testComponent.runTest { val position by collectLastValue(underTest.position) // When not in split shade @@ -282,7 +279,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun positionOnLockscreenInSplitShade() = - testScope.runTest { + testComponent.runTest { val position by collectLastValue(underTest.position) // When in split shade @@ -304,7 +301,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun positionOnShade() = - testScope.runTest { + testComponent.runTest { val position by collectLastValue(underTest.position) // Start on lockscreen with shade expanded @@ -321,7 +318,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun positionOnQS() = - testScope.runTest { + testComponent.runTest { val position by collectLastValue(underTest.position) // Start on lockscreen with shade expanded @@ -338,7 +335,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun maxNotificationsOnLockscreen() = - testScope.runTest { + testComponent.runTest { whenever( notificationStackSizeCalculator.computeMaxKeyguardNotifications( any(), @@ -363,7 +360,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { @Test fun maxNotificationsOnShade() = - testScope.runTest { + testComponent.runTest { whenever( notificationStackSizeCalculator.computeMaxKeyguardNotifications( any(), @@ -387,66 +384,36 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { assertThat(maxNotifications).isEqualTo(-1) } - private suspend fun TestScope.showLockscreen() { + private suspend fun TestComponent.showLockscreen() { shadeRepository.setLockscreenShadeExpansion(0f) shadeRepository.setQsExpansion(0f) keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD) keyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN, - this, + testScope, ) } - private suspend fun TestScope.showLockscreenWithShadeExpanded() { + private suspend fun TestComponent.showLockscreenWithShadeExpanded() { shadeRepository.setLockscreenShadeExpansion(1f) shadeRepository.setQsExpansion(0f) keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED) keyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN, - this, + testScope, ) } - private suspend fun TestScope.showLockscreenWithQSExpanded() { + private suspend fun TestComponent.showLockscreenWithQSExpanded() { shadeRepository.setLockscreenShadeExpansion(0f) shadeRepository.setQsExpansion(1f) keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED) keyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN, - this, + testScope, ) } - - @SysUISingleton - @Component( - modules = - [ - SysUITestModule::class, - UserDomainLayerModule::class, - ] - ) - interface TestComponent { - - val underTest: SharedNotificationContainerViewModel - - val configurationRepository: FakeConfigurationRepository - val keyguardRepository: FakeKeyguardRepository - val keyguardInteractor: KeyguardInteractor - val keyguardTransitionRepository: FakeKeyguardTransitionRepository - val shadeRepository: FakeShadeRepository - val sharedNotificationContainerInteractor: SharedNotificationContainerInteractor - val testScope: TestScope - - @Component.Factory - interface Factory { - fun create( - @BindsInstance test: SysuiTestCase, - featureFlags: FakeFeatureFlagsClassicModule, - mocks: TestMocksModule, - ): TestComponent - } - } }