1 /* <lambda>null2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.media.controls.ui.animation 18 19 import android.animation.ValueAnimator 20 import android.graphics.Color 21 import android.testing.TestableLooper 22 import androidx.test.ext.junit.runners.AndroidJUnit4 23 import androidx.test.filters.SmallTest 24 import com.android.systemui.SysuiTestCase 25 import com.android.systemui.media.controls.ui.view.GutsViewHolder 26 import com.android.systemui.media.controls.ui.view.MediaViewHolder 27 import com.android.systemui.monet.ColorScheme 28 import com.android.systemui.surfaceeffects.ripple.MultiRippleController 29 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController 30 import junit.framework.Assert.assertEquals 31 import org.junit.After 32 import org.junit.Before 33 import org.junit.Rule 34 import org.junit.Test 35 import org.junit.runner.RunWith 36 import org.mockito.Mock 37 import org.mockito.Mockito.never 38 import org.mockito.Mockito.times 39 import org.mockito.Mockito.verify 40 import org.mockito.Mockito.`when` as whenever 41 import org.mockito.junit.MockitoJUnit 42 43 private const val DEFAULT_COLOR = Color.RED 44 private const val TARGET_COLOR = Color.BLUE 45 46 @SmallTest 47 @RunWith(AndroidJUnit4::class) 48 @TestableLooper.RunWithLooper(setAsMainLooper = true) 49 class ColorSchemeTransitionTest : SysuiTestCase() { 50 51 private interface ExtractCB : (ColorScheme) -> Int 52 private interface ApplyCB : (Int) -> Unit 53 private lateinit var colorTransition: AnimatingColorTransition 54 private lateinit var colorSchemeTransition: ColorSchemeTransition 55 56 @Mock private lateinit var mockAnimatingTransition: AnimatingColorTransition 57 @Mock private lateinit var valueAnimator: ValueAnimator 58 @Mock private lateinit var colorScheme: ColorScheme 59 @Mock private lateinit var extractColor: ExtractCB 60 @Mock private lateinit var applyColor: ApplyCB 61 62 private lateinit var animatingColorTransitionFactory: AnimatingColorTransitionFactory 63 @Mock private lateinit var mediaViewHolder: MediaViewHolder 64 @Mock private lateinit var gutsViewHolder: GutsViewHolder 65 @Mock private lateinit var multiRippleController: MultiRippleController 66 @Mock private lateinit var turbulenceNoiseController: TurbulenceNoiseController 67 68 @JvmField @Rule val mockitoRule = MockitoJUnit.rule() 69 70 @Before 71 fun setUp() { 72 whenever(mediaViewHolder.gutsViewHolder).thenReturn(gutsViewHolder) 73 animatingColorTransitionFactory = { _, _, _ -> mockAnimatingTransition } 74 whenever(extractColor.invoke(colorScheme)).thenReturn(TARGET_COLOR) 75 76 colorSchemeTransition = 77 ColorSchemeTransition( 78 context, 79 mediaViewHolder, 80 multiRippleController, 81 turbulenceNoiseController, 82 animatingColorTransitionFactory 83 ) 84 85 colorTransition = 86 object : AnimatingColorTransition(DEFAULT_COLOR, extractColor, applyColor) { 87 override fun buildAnimator(): ValueAnimator { 88 return valueAnimator 89 } 90 } 91 } 92 93 @After fun tearDown() {} 94 95 @Test 96 fun testColorTransition_nullColorScheme_keepsDefault() { 97 colorTransition.updateColorScheme(null) 98 verify(applyColor, times(1)).invoke(DEFAULT_COLOR) 99 verify(valueAnimator, never()).start() 100 assertEquals(DEFAULT_COLOR, colorTransition.sourceColor) 101 assertEquals(DEFAULT_COLOR, colorTransition.targetColor) 102 } 103 104 @Test 105 fun testColorTransition_newColor_startsAnimation() { 106 colorTransition.updateColorScheme(colorScheme) 107 verify(applyColor, times(1)).invoke(DEFAULT_COLOR) 108 verify(valueAnimator, times(1)).start() 109 assertEquals(DEFAULT_COLOR, colorTransition.sourceColor) 110 assertEquals(TARGET_COLOR, colorTransition.targetColor) 111 } 112 113 @Test 114 fun testColorTransition_sameColor_noAnimation() { 115 whenever(extractColor.invoke(colorScheme)).thenReturn(DEFAULT_COLOR) 116 colorTransition.updateColorScheme(colorScheme) 117 verify(valueAnimator, never()).start() 118 assertEquals(DEFAULT_COLOR, colorTransition.sourceColor) 119 assertEquals(DEFAULT_COLOR, colorTransition.targetColor) 120 } 121 122 @Test 123 fun testColorTransition_colorAnimation_startValues() { 124 val expectedColor = DEFAULT_COLOR 125 whenever(valueAnimator.animatedFraction).thenReturn(0f) 126 colorTransition.updateColorScheme(colorScheme) 127 colorTransition.onAnimationUpdate(valueAnimator) 128 129 assertEquals(expectedColor, colorTransition.currentColor) 130 assertEquals(expectedColor, colorTransition.sourceColor) 131 verify(applyColor, times(2)).invoke(expectedColor) // applied once in constructor 132 } 133 134 @Test 135 fun testColorTransition_colorAnimation_endValues() { 136 val expectedColor = TARGET_COLOR 137 whenever(valueAnimator.animatedFraction).thenReturn(1f) 138 colorTransition.updateColorScheme(colorScheme) 139 colorTransition.onAnimationUpdate(valueAnimator) 140 141 assertEquals(expectedColor, colorTransition.currentColor) 142 assertEquals(expectedColor, colorTransition.targetColor) 143 verify(applyColor).invoke(expectedColor) 144 } 145 146 @Test 147 fun testColorTransition_colorAnimation_interpolatedMidpoint() { 148 val expectedColor = Color.rgb(186, 0, 186) 149 whenever(valueAnimator.animatedFraction).thenReturn(0.5f) 150 colorTransition.updateColorScheme(colorScheme) 151 colorTransition.onAnimationUpdate(valueAnimator) 152 153 assertEquals(expectedColor, colorTransition.currentColor) 154 verify(applyColor).invoke(expectedColor) 155 } 156 157 @Test 158 fun testColorSchemeTransition_update() { 159 colorSchemeTransition.updateColorScheme(colorScheme) 160 verify(mockAnimatingTransition, times(8)).updateColorScheme(colorScheme) 161 verify(gutsViewHolder).colorScheme = colorScheme 162 } 163 } 164