1 /*
2  * Copyright (C) 2023 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
18 
19 import android.testing.AndroidTestingRunner
20 import android.testing.TestableLooper
21 import android.view.MotionEvent
22 import androidx.test.filters.SmallTest
23 import com.android.systemui.SysuiTestCase
24 import com.android.systemui.classifier.FalsingCollector
25 import com.android.systemui.media.controls.util.MediaUiEventLogger
26 import com.android.systemui.plugins.FalsingManager
27 import com.android.systemui.qs.PageIndicator
28 import com.android.systemui.util.concurrency.FakeExecutor
29 import com.android.systemui.util.mockito.eq
30 import com.android.systemui.util.mockito.whenever
31 import com.android.systemui.util.time.FakeSystemClock
32 import org.junit.Before
33 import org.junit.Test
34 import org.junit.runner.RunWith
35 import org.mockito.Mock
36 import org.mockito.Mockito.anyInt
37 import org.mockito.Mockito.verify
38 import org.mockito.MockitoAnnotations
39 
40 @SmallTest
41 @TestableLooper.RunWithLooper(setAsMainLooper = true)
42 @RunWith(AndroidTestingRunner::class)
43 class MediaCarouselScrollHandlerTest : SysuiTestCase() {
44 
45     private val carouselWidth = 1038
46     private val motionEventUp = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0f, 0f, 0)
47 
48     @Mock lateinit var mediaCarousel: MediaScrollView
49     @Mock lateinit var pageIndicator: PageIndicator
50     @Mock lateinit var dismissCallback: () -> Unit
51     @Mock lateinit var translationChangedListener: () -> Unit
52     @Mock lateinit var seekBarUpdateListener: (visibleToUser: Boolean) -> Unit
53     @Mock lateinit var closeGuts: (immediate: Boolean) -> Unit
54     @Mock lateinit var falsingCollector: FalsingCollector
55     @Mock lateinit var falsingManager: FalsingManager
56     @Mock lateinit var logSmartspaceImpression: (Boolean) -> Unit
57     @Mock lateinit var logger: MediaUiEventLogger
58 
59     lateinit var executor: FakeExecutor
60     private val clock = FakeSystemClock()
61 
62     private lateinit var mediaCarouselScrollHandler: MediaCarouselScrollHandler
63 
64     @Before
65     fun setup() {
66         MockitoAnnotations.initMocks(this)
67         executor = FakeExecutor(clock)
68         mediaCarouselScrollHandler =
69             MediaCarouselScrollHandler(
70                 mediaCarousel,
71                 pageIndicator,
72                 executor,
73                 dismissCallback,
74                 translationChangedListener,
75                 seekBarUpdateListener,
76                 closeGuts,
77                 falsingCollector,
78                 falsingManager,
79                 logSmartspaceImpression,
80                 logger
81             )
82         mediaCarouselScrollHandler.playerWidthPlusPadding = carouselWidth
83 
84         whenever(mediaCarousel.touchListener).thenReturn(mediaCarouselScrollHandler.touchListener)
85     }
86 
87     @Test
88     fun testCarouselScroll_shortScroll() {
89         whenever(mediaCarousel.isLayoutRtl).thenReturn(false)
90         whenever(mediaCarousel.relativeScrollX).thenReturn(300)
91 
92         mediaCarousel.touchListener?.onTouchEvent(motionEventUp)
93         executor.runAllReady()
94 
95         verify(mediaCarousel).smoothScrollTo(eq(0), anyInt())
96     }
97 
98     @Test
99     fun testCarouselScroll_shortScroll_isRTL() {
100         whenever(mediaCarousel.isLayoutRtl).thenReturn(true)
101         whenever(mediaCarousel.relativeScrollX).thenReturn(300)
102 
103         mediaCarousel.touchListener?.onTouchEvent(motionEventUp)
104         executor.runAllReady()
105 
106         verify(mediaCarousel).smoothScrollTo(eq(carouselWidth), anyInt())
107     }
108 
109     @Test
110     fun testCarouselScroll_longScroll() {
111         whenever(mediaCarousel.isLayoutRtl).thenReturn(false)
112         whenever(mediaCarousel.relativeScrollX).thenReturn(600)
113 
114         mediaCarousel.touchListener?.onTouchEvent(motionEventUp)
115         executor.runAllReady()
116 
117         verify(mediaCarousel).smoothScrollTo(eq(carouselWidth), anyInt())
118     }
119 
120     @Test
121     fun testCarouselScroll_longScroll_isRTL() {
122         whenever(mediaCarousel.isLayoutRtl).thenReturn(true)
123         whenever(mediaCarousel.relativeScrollX).thenReturn(600)
124 
125         mediaCarousel.touchListener?.onTouchEvent(motionEventUp)
126         executor.runAllReady()
127 
128         verify(mediaCarousel).smoothScrollTo(eq(0), anyInt())
129     }
130 }
131